Created
November 15, 2016 10:31
-
-
Save sbliven/f7babb729e0b1bee8d2dabe5ee979431 to your computer and use it in GitHub Desktop.
Reduction of biojava/biojava#354 into a form suitable for asking at http://stackoverflow.com/questions/40598972/java-two-level-parameterized-type-inference
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package demo; | |
import java.util.ArrayList; | |
import java.util.Collection; | |
import java.util.Collections; | |
import java.util.List; | |
import java.util.Set; | |
public class GenericsHell { | |
static class NumberLists<L extends List<T>,T extends Number> extends ArrayList<L> {} | |
static <L extends List<T>,T extends Number> | |
Set<NumberLists<L,T>> useList(L list) { | |
NumberLists<L,T> nl = new NumberLists<L, T>(); | |
nl.add(list); | |
return Collections.singleton(nl); | |
} | |
// Note that this is not assignable to List<Number> | |
static List<? extends Number> makeList() { | |
if(Math.random()<.5) { | |
return new ArrayList<Integer>(); | |
} else { | |
return new ArrayList<Double>(); | |
} | |
} | |
static <L extends List<T>,T extends Number> | |
NumberLists<L,T> createAndAdd(L list) { | |
NumberLists<L,T> paraNL = new NumberLists<>(); | |
paraNL.add(list); | |
return paraNL; | |
} | |
public static void main(String[] args) { | |
// Everything works with a concrete class | |
List<Integer> intList = new ArrayList<Integer>(); | |
// Use with parametric functions | |
Set<NumberLists<List<Integer>,Integer>> concreteSet = useList(intList); | |
// Create related class of the same type | |
NumberLists<List<Integer>,Integer> concreteNL = concreteSet.iterator().next(); | |
concreteNL.add(intList); | |
// But now I need to handle the case where the input is also parametric | |
List<? extends Number> numList = makeList(); | |
// What is the type here? This is obviously an error | |
Set<NumberLists<? extends List<? extends Number>>,? extends Number> paramSet = useList(numList); | |
// Type should ideally be compatible with numList still | |
NumberLists<?,?> paraNL1 = paramSet.iterator().next(); | |
// Captures don't match | |
paraNL1.add(numList); | |
// Can't even add numList to a NumberLists, since clusters don't match | |
NumberLists<?,?> paraNL2 = new NumberLists<>(); | |
paraNL2.add(numList); | |
// Have to work around this with a parametric method that does both steps | |
NumberLists<?,?> paraNL3 = createAndAdd(numList); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment