I have some code that returns a wildcard parameterized type. I'm trying to pass this to a parametric method, but I get a compiler error. Can someone explain to me why the types are not matched, and what the best way to fix this is?
static <L extends List<T>,T extends Number>
void useList(List<L> list) {}
public static void main(String[] args) {
    List<List<? extends Number>> list = null;
    useList(list);
}
Compile error:
demo/GenericsHell.java:75: error: method useList in class GenericsHell cannot be applied to given types;
        useList(list);
        ^
  required: List<L>
  found: List<List<? extends Number>>
  reason: inference variable L has incompatible bounds
    equality constraints: List<? extends Number>
    upper bounds: List<CAP#1>
  where L,T are type-variables:
    L extends List<T> declared in method <L,T>useList(List<L>)
    T extends Number declared in method <L,T>useList(List<L>)
  where CAP#1 is a fresh type-variable:
    CAP#1 extends Number from capture of ? extends Number
1 error
In my real code list is being generated by a complex method that can return several types of "List" (actually a custom generic class). Is there another way to parameterize the useList function such that it will accept this in a type-safe way?
Edit 1
I am trying to reduce a large module of code into a concise, coherent question. From the answers I can see that the above code over-simplifies the precise problem I'm having. I'll try to restate with a more complex example, while better specifying my constraints.
First off, I'm not actually using List, but rather a more complex class with a double parameterization. I can't think of any standard classes that do this, so I'll define one for use in the example:
static class NumberLists<L extends List<T>,T extends Number> extends ArrayList<L> {}
I'll avoid reusing a type more than once, so it's easier to keep the levels straight. The useList() method really does need a double parameterization because it uses both types internally:
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);
}
This framework works great as long as you have a concrete class:
    // Everything works with a concrete class
    List<Integer> intList = new ArrayList<Integer>();
    // Use with parametric functions
    Set<NumberLists<List<Integer>,Integer>> concreteSet = useList(intList);
    // Access & use elements
    NumberLists<List<Integer>,Integer> concreteNL = concreteSet.iterator().next();
    concreteNL.add(intList);
The problem is that I have an input list that can be several different types:
static List<? extends Number> makeList() {
    if(Math.random()<.5) {
        return new ArrayList<Integer>();
    } else {
        return new ArrayList<Double>();
    }
}
List<? extends Number> numList = makeList();
This breaks many of the patterns that were possible above.
    // 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);
So the problem is that I can't know the concrete class of numList at compile time. And it doesn't feel like I'm doing anything that's actually type-unsafe, since I know that the type of numList has to match the type returned by useList and so on.
I do have control over the type signatures of most parts of the code. However, I would prefer the following:
- It should work nicely and in a type-safe manner with concrete classes (e.g. intList)
- It will also receive input whose type can't be known specifically until runtime
- If casts or other unchecked operations are performed, they should happen near the construction of the input. Following operations should be checked.
For a complete (but non-compiling) java file, see https://gist.github.com/sbliven/f7babb729e0b1bee8d2dabe5ee979431. For the reason I'm interested in this question, see https://github.com/biojava/biojava/issues/354.
 
     
     
    