Community
Participate
Working Groups
For an enum containing an abstract method with a non-primitive return type: if any of the enum elements implements the method with a covariant return type, an AbstractMethodError will be thrown when the method is invoked on that element. The following test case succeeds when compiled with the Sun JDK compiler, but fails when compiled in Eclipse. Tested against Eclipse 3.1_I20050126-0800 ---- EnumElementCovariantReturnTest.java ---- import junit.framework.TestCase; public class EnumElementCovariantReturnTest extends TestCase { // this test passes public void testEnumElementNormalReturn() { E.ITEM_1.x(); } // this test fails due to covariant return value in ITEM_2 public void testEnumElementCovariantReturn() { E.ITEM_2.x(); } static class X {} static class Y extends X {} enum E { ITEM_1() { // regular return value -- works as expected public X x() { return new Y(); } }, ITEM_2() { // covariant return -- AbstractMethodError public Y x() { return new Y(); } }; public abstract X x(); } } ---- End of EnumElementCovariantReturnTest.java ---- Now replace the abstract declaration of x() with the following: public X x() { throw new UnsupportedOperationException(); } Run the test case, and an UnsupportedOperationException will be thrown. It seems the compiler does not recognize that E.ITEM_2.x() is overriding E.x(). Therefore it would also seem in the original test case above that the compiler does not recognize that ITEM_2.x() is implementing the abstract method E.x().
We can't be sure this bug is really fixed until 83901 is fixed.
I'm encountering an AbstractMethodError involving a covariant return override as well. Mine has nothing to do with enums, and is with build I20050202-0800. My class hierarchy is very complex, and I don't have a small reproducer yet, but a summary is: interface Visibility {} interface NamedObject {} interface Function extends NamedObject {} interface ClassMember { Visibility getVisibility(); } class FooVisibility implements Visibility {} class FooFunction implements Function { FooVisibility getVisibility(); } interface FooClassMember { FooVisibility getVisibility(); } class FooMemberFunction extends FooFunction implements FooClassMember {} void foo(NamedObject o) { ClassMember member = (ClassMember) o; member.getVisibility(); // AbstractMethodError }
Forgot to add: foo() is called with a FooMemberFunction object.
Here's a reproducer: public final class Bug83902 { public interface Visibility { } public interface Function { } public interface ClassMember { Visibility getVisibility(); } public interface MemberFunction extends Function, ClassMember { } public static class FooVisibility implements Visibility { public static final FooVisibility PUBLIC = new FooVisibility(); } public static class FooFunction implements Function { public FooVisibility getVisibility() { return FooVisibility.PUBLIC; } } interface FooClassMember extends ClassMember { FooVisibility getVisibility(); } public static class FooMemberFunction extends FooFunction implements MemberFunction, FooClassMember { } public static void main(String[] args) { FooMemberFunction fmf = new FooMemberFunction(); fmf.getVisibility(); // OK FooClassMember fcm = fmf; fcm.getVisibility(); // OK ClassMember cm = fmf; cm.getVisibility(); // AbstractMethodError } } Exception in thread "main" java.lang.AbstractMethodError: Bug83902$FooMemberFunction.getVisibility()LBug83902$Visibility; at Bug83902.main(Bug83902.java:55)
On second scenario, we are missing one bridge method on FooMemberFunction: public bridge synthetic X.IVisibility getVisibility();
the problem in comment 0 is fixed. the missing bridge method problem in comment 4 can be reproduced with: public class X { interface I {} interface J { I getVisibility(); } static class A implements I {} static class B { public A getVisibility() { return null; } } static class C extends B implements J {} public static void main(String[] args) { C c = new C(); c.getVisibility(); // OK J j = c; j.getVisibility(); // AbstractMethodError } } We are missing the bridge method on the class C because of the inherited methods from B & J
Added EnumTest test076 for comment 0. Added MethodVerifyTest test041 for comment 6
Verified in I20050215-2300