Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Generics and overridding

Tags:

java

generics

Why does the following happen:

public class one{
   public <T extends Foo> Bar<Foo> function1() {}
   public Bar<Foo> function2(){}
}
public class two<F extends Foo> extends one{
   public Bar<F> function1(){} //Doesn't throw an error
   public Bar<F> function2(){} //Throws an error
}

By saying <T extends Foo> am I saying that Foo can be overridden with a super type?

Note: My question is not why function2() throws an error...but why function1() doesn't throw an error.

like image 616
Nathan Merrill Avatar asked Sep 05 '13 19:09

Nathan Merrill


1 Answers

This is probably a compiler bug.

The reason that Two.function1 is considered an overriding method of One.function1 is from http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.4.2

the signature of Two.function1 is the same as the erasure of the signature of One.function1.

This is to allow legacy subtype (Two) still compile after a supertype (One) is generified.

After that, javac needs to check the return type:

http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.4.8.3

If a method declaration d1 with return type R1 overrides or hides the declaration of another method d2 with return type R2, then d1 must be return-type-substitutable (§8.4.5) for d2, or a compile-time error occurs.

http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.4.5

R1 is either a subtype of R2 or R1 can be converted to a subtype of R2 by unchecked conversion (§5.1.9), or R1 = |R2|

http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.9

There is an unchecked conversion from the raw class or interface type (§4.8) G to any parameterized type of the form G.

Unchecked conversion does not apply here where R1=Bar<F>, R2=Bar<Foo>. That's why Javac reports that function2 return type is conflicting.

Javac should report the same error for function1. I'm guessing that in a previous step, javac took the erasure of One.function1, which is Bar function1(), and mistakenly uses that version to check against Two.function1 - here R2=Bar, therefore R1 is a subtype($4.10.2) of R2, therefore the return type is compatible. (However, if that theory is correct, there shouldn't be a "unchecked" warning)

like image 104
ZhongYu Avatar answered Oct 09 '22 01:10

ZhongYu