Why is conversion to "GenericType <?>" Not allowed here?
This code causes a compilation error using javac (but in particular not with Eclipse 4.2.2!):
public interface Foo<T> { } class Bar<T> implements Foo<Iterable<T>> { } class Test { void test(Foo<? extends Iterable<? extends String>> foo) { Bar<?> bar = (Bar<?>) foo; } } Javac error:
Foo.java:9: error: inconvertible types Bar<?> bar = (Bar<?>) foo; ^ required: Bar<?> found: Foo<CAP#1> where CAP#1 is a fresh type-variable: CAP#1 extends Iterable<? extends String> from capture of ? extends Iterable<? extends String> Changing the cast to (Bar) foo (i.e. using a raw type) allows you to compile the code, just like changing the type foo to just Foo<? extends Iterable<?>> Foo<? extends Iterable<?>> .
EDIT: Fun, this simple change causes Eclipse to stray, but javac accepts:
void test(Foo<Iterable<String>> foo) { Bar<?> bar = (Bar<?>) foo; } And, both Eclipse and javac reject this:
void test(Foo<Iterable<? extends String>> foo) { Bar<?> bar = (Bar<?>) foo; } If a programmer wants to explicitly indicate type X to type Y , the language can simply allow this, assuming that the programmer knows better than the compiler.
But the good guys in Java want to prevent some apparently impossible throws, for example. (Cat)dog . So they have this great detailed topic section - http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.5.1
But are there any problems with these rules? And do compilers comply with these rules? ... These questions are too complicated and not very interesting.
We need to take care of whether the cast makes sense; if that makes sense and the compiler refuses to accept it, no problem, just get around it.
There are two places in your question for inserting wildcards, in Foo< > and in Iterable< > . In each place, a wildcard can be
0. None 1. Bounded "? extends Something" 2. Unbounded "?" so let's explore all the combinations, and here is my conclusion:
wildcard#1 wildcard#2 should_compile javac eclipse 00 - - YYN 01 - ? extends NNN 02 - ? NNN 10 ? extends - YNY 11 ? extends ? extends YNY 12 ? extends ? YYY 20 ? - YYY should_compile means casting makes sense or is not explained later.
In case of 10 and 11 code should compile, but javac rejects it. Either the rules have problems, or javac has errors.
Let us see, for example, why register 00 makes sense and should compile
void test00(Foo<Iterable<String>> foo) { Bar<?> bar = (Bar<?>) foo; } the question is, could there be a class/interface `X`, such that Bar<X> <: Foo<Iterable<String>> => Foo<Iterable<X>> <: Foo<Iterable<String>> => Iterable<X> = Iterable<String> => X = String so the answer is yes, the cast makes sense. and why case 01 should not compile
Foo<Iterable<X>> <: Foo<Iterable<? extends String>> => Iterable<X> = Iterable<? extends String> => NO SOLUTION note that Iterable<String> != Iterable<? extends String> and case 11
Foo<Iterable<X>> <: Foo<? extends Iterable<? extends String>> => Iterable<X> <: Iterable<? extends String> => X <: String Surprisingly, case 01 should not be compiled, although it feels reasonable. Root problem: Iterable is convariant, and we should use a wildcard with it almost wherever it was used. Therefore, ideally, we should declare
class Bar<T> implements Foo<Iterable<? extends T>> but life is hell if we insert wildcards everywhere. The best solution is to disperse your ad site. Not sure if Java will ever add this feature before we all retire.
Your code is reasonable and should compile: are you reducing the static type of Foo to Bar , extending the generic type ? extends Iterable<? extends String> ? extends Iterable<? extends String> ? extends Iterable<? extends String> to ? where is the top level ? is a wildcard, This is a verified listing, and it should compile without warning.
You must send an Oracle error . I tried to find the appropriate error report, but this old closed ticket was the closest to this problem (IMO. Oracle Database is very difficult to find). I will look more when I get a chance, because this javac problem seems very familiar.