2

我刚刚查看了TimeUnit 枚举源代码(简化如下):

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扔吗?如果是,在哪种情况下?

4

2 回答 2

3

abstract标准 doclet(即 Sun/Oracle 品种)在 Javadoc 输出中不提供枚举方法。如果这些方法是抽象的,Javadoc 就不会显示它们的踪迹。这个错误仍然存​​在,最初是在 2005 年(9 年前)报告的:

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

如果要实现正确的行为,这些方法将出现在 Javadoc 输出中,并去掉抽象关键字。枚举值本质上是枚举类的匿名子类,因此 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 的脚步。

于 2014-02-19T08:20:24.937 回答
1

只能在枚举值之一未能覆盖该方法或调用超类方法时引发异常。我不推荐这种特定的方法。让编译器捕获这些错误要好得多,因为您建议的替代方案可以完成。

顺便说一句,在我看来,toMillis实现肯定是错误的。MINUTES这不是我拥有的 Java 7 源代码中的实现。你在哪里找到它?

PS我刚刚检查过:Android实现TimeUnit不使用AbstractMethodError,但也不使用抽象方法。它使用各种表格,并在enum级别上实现了所有的转换方法。

于 2013-08-21T14:59:10.443 回答