抛出AbstractMethodError VS抽象方法的经典方法

时间:2013-08-21 14:54:10

标签: java enums abstract

我刚看了TimeUnit enum源代码(以下简化):

public enum TimeUnit {

    SECONDS {
        public long toMillis(long d) { return d * 1000L; }
    },
    MINUTES {
        public long toMillis(long d) { return d * 60000L; }
    };

    public long toMillis(long duration) {
        throw new AbstractMethodError();
    }

}

他们也可以使用抽象方法实现它:

public enum TimeUnit {

    SECONDS {...}, MINUTES {...};

    public abstract long toMillis(long duration);

}

由于他们选择了第一个实现,我猜必须有一个原因。因此,我的问题是:为什么?可以抛出AbstractMethodError吗?如果是,在哪种情况下?

2 个答案:

答案 0 :(得分:3)

标准doclet(即Sun / Oracle种类)在Javadoc输出中不提供abstract枚举方法。如果这些方法是抽象的,那么Javadoc就不会显示它们的痕迹。这个bug仍然是开放的,最初是在2005年(9年前)报道的:

JDK-6287639:枚举类中的抽象方法不应列为抽象方法 http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6287639

如果要实现正确的行为,这些方法将出现在Javadoc输出中,并删除了abstract关键字。枚举值本质上是枚举类的匿名子类,因此javac确保枚举值实现每个抽象方法。因此,从外部观察者的角度来看,抽象枚举方法实际上是非抽象的。

以下评论在TimeUnit的实现中提供了更多的见解:

// To maintain full signature compatibility with 1.5, and to improve the
// clarity of the generated javadoc (see 6287639: Abstract methods in
// enum classes should not be listed as abstract), method convert
// etc. are not declared abstract but otherwise act as abstract methods.

如果Javadoc对您的项目很重要,您可能需要考虑遵循TimeUnit的脚步。

答案 1 :(得分:1)

只能抛出其中一个枚举值无法覆盖该方法,或者它调用超类方法的异常。我不推荐这种特殊方法;让编译器捕获这些错误要好得多,因为建议的替代方案可以完成。

顺便说一句,toMillis的{​​{1}}实施确实对我来说不对。这不是我拥有的Java 7源代码的实现。你在哪里找到的?

P.S。我刚检查过:MINUTES的Android实现不使用TimeUnit,但它也不使用抽象方法。它使用各种表格并实现AbstractMethodError级别的所有转换方法。

相关问题