abstract method in indirect superclass

Dan Smith daniel.smith at oracle.com
Mon Aug 26 15:36:06 PDT 2013


On Aug 22, 2013, at 4:36 PM, Stephan Herrmann <stephan.herrmann at berlin.de> wrote:

> On 07/12/2013 08:59 PM, Dan Smith wrote:
>> I immediately thought of this bug:
>> http://bugs.sun.com/view_bug.do?bug_id=8010681
> 
> Is the following example related, or covered by some previous
> discussion? Sorry, if this is off-topic for this list:
> 
>    class A {}
>    class B extends A {}
>    class C extends B {}
> 
>    abstract class Test1<T1 extends A> {
>        abstract void foo(T1 param1);
>    }
> 
>    abstract class Test2<T2 extends B> extends Test1<T2> {
>        @Override
>        void foo(B param2) {
>            System.out.println("2 " + param2);
>        }
>    }
> 
>    public class Test3 extends Test2<C> {
>        @Override
>        void foo(C param3) {
>            System.out.println("3 " + param3);
>        }
>    }
> 
> Here Test3 has two *independent* overrides of the same root,
> yet none of the compilers complains.
> If the override in Test2 cannot be undone, as Dan says,
> how can we override the same method Test1.foo again?
> 
> Of course, Test3.foo(C) cannot override Test2.foo(B),
> but shouldn't it then be interpreted as an entirely
> new method, not overriding anything?
> 
> Note that bridges for these unrelated methods
> do override each other. The outcome of this snippet
> is determined by this accidental overriding of bridges:
>  Test1 t = new Test3(); // either raw Test1 or Test1<C>, same byte code produced
>  t.foo(new C()); // invokes Test3.foo via its bridge, which overrides the bridge in Test2
> 
> This looks scary to me...

Similar, yes, and weird, yes, but here I don't see a problem.  When you invoke Test1.foo, the behavior is to execute Test3.foo, which makes sense because Test3.foo overrides Test1.foo, and it's the "bottom-most" method to do so.  On the other hand, Test3.foo _does not_ override Test2.foo, and, in fact, if you try to invoke Test2.foo, that's what will execute.  (There is no bridge in Test3 that overrides foo(B).)  So everything seems to be consistent...

(It's true that 15.12.4.4 doesn't account for generics/erasure/bridges in its description of the behavior of invocation, so this is all a little fuzzy.)

—Dan


More information about the lambda-spec-observers mailing list