java - Why isn't a conversion to "GenericType<?>" allowed here? -


this code causes compile error javac (but, notably, not 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;     } } 

the error javac this:

foo.java:9: error: inconvertible types         bar<?> bar = (bar<?>) foo;                               ^   required: bar<?>   found:    foo<cap#1>   cap#1 fresh type-variable:     cap#1 extends iterable<? extends string> capture of ? extends iterable<? extends string> 

changing cast (bar) foo (i.e. using raw type) allows code compile, changing type of foo foo<? extends iterable<?>>.

edit: hilariously, simple change causes eclipse reject, javac accept:

void test(foo<iterable<string>> foo) {     bar<?> bar = (bar<?>) foo; } 

and, both eclipse , javac reject one:

void test(foo<iterable<? extends string>> foo) {     bar<?> bar = (bar<?>) foo; } 

if programmer wants explicitly cast type x type y, language allow it, assuming programmer knows better compiler.

but guys @ java want prevent impossible casts, e.g. (cat)dog. have glorious detailed section dedicated subject - http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.5.1

but, there problems these rules? and, compilers conform these rules? ... these questions complex , not interesting.

what should care whether cast makes sense; if make sense, , compiler refuses accept it, no problem, work around it.


in question, there 2 places insert wildcards, in foo< >, , in iterable< >. in each place, wildcard can

    0. none     1. bounded    "? extends something"     2. unbounded  "?" 

so let's explore combinations, , here's conclusion:

     wildcard#1    wildcard#2     should_compile   javac     eclipse  00   -             -              y                y         n 01   -             ? extends      n                n         n 02   -             ?              n                n         n 10   ? extends     -              y                n         y 11   ? extends     ? extends      y                n         y 12   ? extends     ?              y                y         y 20   ?             -              y                y         y 

should_compile means cast makes sense or not, explained later.

in case 10 , 11, code should compile, javac rejects it. either rules have problems, or javac has bugs.


let's see example, why case 00 makes sense , should compile

void test00(foo<iterable<string>> foo) {     bar<?> bar = (bar<?>) foo; }  question is, there class/interface `x`, such       bar<x> <: foo<iterable<string>>  =>    foo<iterable<x>> <: foo<iterable<string>>  =>    iterable<x> = iterable<string> =>    x = string answer yes, 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 iterable<string> != iterable<? extends string> 

and case 11

     foo<iterable<x>>  <: foo<? extends iterable<? extends string>> =>   iterable<x> <: iterable<? extends string> =>   x <: string 

it surprising case 01 should not compile, although feels sensible. root problem is, iterable convariant, , ought use wildcard anywhere it's used. ideally should declare

class bar<t> implements foo<iterable<? extends t>> 

but life hell if insert wildcards everywhere. better solution declaration site variance. not sure if java ever add feature before retire.


Comments

Popular posts from this blog

php - Calling a template part from a post -

Firefox SVG shape not printing when it has stroke -

How to mention the localhost in android -