2011-03-25 337 views
9

我有一些關於java中註釋工作的問題。編譯器如何處理註釋?

如果註釋不能轉換爲字節碼,那麼這些信息會去哪裏? 元數據在哪裏? Java Reflection如何使用此信息?

編譯器如何處理註釋?

當我們說,

@Override 
public void doSomething(){ 
} 

什麼是一個Java編譯器做呢?

我知道它檢查方法簽名,以便該方法應該是一個完全覆蓋的方法,但是如何?

+0

看看這是否有幫助http://pawanz.wordpress.com/2010/12/12/taming-java-annotations/ – ashishjmeshram 2011-03-25 12:54:20

回答

0

這個很簡單。編譯器只檢查超類,查找具有相同名稱和相同參數數量,它們的順序和類型的方法。如果方法有@Override註釋,並且尚未找到此方法,則會生成錯誤。

更有趣的問題是編譯器如何處理在運行時具有意義的註釋。我假設它們是以字節碼形式添加的,但是在一些特殊的元信息部分。所以,在運行時jvm可以訪問meta部分。作爲證明,您始終可以在任何class對象上致電getAnnotations()

4

@Override類型的註釋 - 用於檢查是否一個特定的方法如下的覆蓋方法的合同 - 因此它不是在運行時可用(並且因此在邏輯上不存在於編譯的字節代碼存在)。

我知道它會檢查方法簽名,這樣的方法應該是一個完全重寫的方法,但如何

在閱讀的源文件,並將它們轉換成字節碼的過程中,例如,不根本不使用反射。有關其他編譯器信息,請參閱The Java Programming Language Compiler - javac

-2

編譯註釋(最終是固定數據)存在於類文件中,並且可以使用適當的方法getAnnotations()和朋友進行訪問。

+0

感謝您的回覆。您能否詳細說明一個「常量池」是什麼,以及它在運行時如何使用。 – Gunwant 2011-03-28 05:00:18

+0

這是存儲常量數據的類文件中的一個區域。您可能需要閱讀JVM參考。 – Ingo 2011-03-28 08:23:05

+0

感謝您提供有用的信息。 – Gunwant 2011-03-29 06:25:44

3

註解e.g作爲public @interface @Override {}實現@Override具有RetentionPolicy,其可以允許所述註釋被存儲在一個類文件(RetentionPolicy.CLASSRetentionPolicy.RUNTIME)或丟棄(RetentionPolicy.SOURCE)。

@Override方法的保留策略爲RetentionPolicy.SOURCE,目標爲ElementType.METHOD(意味着此方法只能在方法聲明上註釋)。

@Target(ElementType.METHOD) 
@Retention(RetentionPolicy.SOURCE) 
public @interface Override { 
} 

PS如果你想反射性地讀取註釋,你將不得不在RetentionPolicy.RUNTIME設置的RetentionPolicy。

2

起初,有兩種註釋:運行時可訪問(2種),不能運行時訪問。註釋的行爲是通過註解聲明的註釋保留策略完成的:-)。例如:

@Retention(RetentionPolicy.RUNTIME) // effectively visible to JVM Runtime 
public @interface MethodInfo { 
    String author() default "unspecified"; 
    String lastModification() default "unspecified"; // Format: yyyy-mm-dd 
    ImplementationStatus implementationStatus(); 
} 

JVM運行時可見註釋可以通過註釋的代碼執行(或當它由JVM加載)時反射來訪問。您將這些註釋用作元數據持有者。元數據可以被其他代碼處理來做各種事情,例如。在執行給定方法之前檢查註釋的方法實現狀態。

但有人必須通過反射編寫代碼才能使用註釋matedata!最好的例子就是應用服務器(AS),它根據需要從JAR文件中加載類是一些特定的目錄。 AS可以包含代碼,用於檢查每個已加載的類是否使用由@Initialization批註註釋的靜態方法,並立即執行這些方法。此註釋類型由AS定義,爲AS創建JAR和類的用戶在開發過程中使用它。

在編譯期間使用並計算出運行時不可用的註釋。 @Override就是很好的例子。編譯器插件可以使用自定義源代碼註釋,或者代碼是由其他代碼按需編譯的。