2013-08-21 59 views
2

我只是在TimeUnit enum源代碼看看(簡體herebelow):經典方法拋出AbstractMethodError VS抽象方法

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可以拋出嗎?如果是,在哪種情況下?

回答

3

標準doclet(即Sun/Oracle品種)在Javadoc輸出中不提供枚舉方法abstract。如果這些方法是抽象的,Javadoc將不會顯示它們的蹤跡。此錯誤仍然是開放的,並在2005年最初報告(9+年前):

JDK-6287639:枚舉類抽象方法不應該被列爲抽象 http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6287639

如果正確的行爲是爲這些方法會在抽象關鍵字被去除的情況下出現在Javadoc輸出中。枚舉值本質上是enum類的匿名子類,所以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

只能拋出其中一個枚舉值的異常無法重寫該方法,或者它調用超類方法。我不推薦這種特殊的方法;更好地讓編譯器捕獲這些錯誤,正如您建議的替代方案所能實現的那樣。

順便說一下,toMillis執行MINUTES肯定看起來不對我。這不是我擁有的Java 7源代碼中的實現。你在哪裏找到它?

P.S.我剛剛檢查:TimeUnit的Android實現不使用AbstractMethodError,但它都不使用抽象方法。它使用各種表格並實現enum級別的所有轉換方法。

+0

你說得對''MINUTES'' toMillis'實現,我剛剛編輯。 – sp00m