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

How to mention the localhost in android -

php - Calling a template part from a post -

c# - String.format() DateTime With Arabic culture -