|
Description
|
Is the compiler right or wrong here?
==========$ cat -n A1.java
1 package p1;
2
3 public class A1<T> {
4 int f(T t) { return 0; }
5 }
==========$ cat -n A2.java
1 package p2;
2
3 public class A2<T> extends p1.A1<T> {}
==========$ cat -n B.java
1 package p1;
2
3 public abstract class B<T,U> extends p2.A2<U> {
4 abstract int f(T t);
5 // abstract I2 f(String s);
6 }
==========$ cat -n C.java
1 package p1;
2
3 public class C extends B<String,String> {
4 // indirect overrider f(String) from A1
5 }
==========$ newjavac *.java
C.java:3: p1.C is not abstract and does not override abstract method f(java.lang.String) in p1.B
public class C extends B<String,String> {
^
1 error
==========$
|
|
Evaluation
|
Nice example. Packages, overriding, overloading, erasure, abstractness - a dream
come true. I think that B is illegal because there are two methods the same
name. different signatures, the same erasure declared in B's hierachy (and
the one in the supertype is accessible to B, since they are in the same
package).
xxxxx@xxxxx 2004-07-09
javac does not give an error on B, therefore this is a compiler bug.
xxxxx@xxxxx 2004-07-09
int f(T t) in p1.A1 is package-private, so is not inherited by p2.A2. (JLS 8.4.8)
Therefore, p1.B doesn't inherit any methods, because its direct superclass p2.A2 doesn't have any. abstract int f(X t) in p1.B (I've renamed B's formal type parameter T to X) doesn't override anything.
p1.C is in the same package as p1.B, so p1.C inherits abstract int f(String t). Since p1.C is not abstract, a compile-time error should occur. As indeed it does.
I presume Gilad missed the accessibility rule that causes p1.A1::f not to be inherited in p2.A2.
Note that **EVEN IF** p2.A2 did inherit int f(T t), it is not the case that abstract int f(X t) in p1.B overrides it. Overriding requires (8.4.8.1 clause (3)) that the overridden member p2.A2::int f(T t) is declared with default access in the same package as p1.B. Not true. Accessibility strikes again.
(For completeness, given m1 = int f(T t), and m2 = abstract int f(X t), where T and X are type variables, m1 has the same signature as m2 according to 8.4.2. Therefore m1 is a subsignature of m2, and m1 and m2 are override-equivalent. Not that this matters here.)
Posted Date : 2006-10-26 15:37:59.0
In order to prevent such confusion again, I'll integrate a regression
test which asserts the behavior above.
I'll also request a JCK-compiler test is developed.
Posted Date : 2006-10-26 16:39:29.0
|