我有一些關於java中註釋工作的問題。編譯器如何處理註釋?
如果註釋不能轉換爲字節碼,那麼這些信息會去哪裏? 元數據在哪裏? Java Reflection如何使用此信息?
編譯器如何處理註釋?
當我們說,
@Override
public void doSomething(){
}
什麼是一個Java編譯器做呢?
我知道它檢查方法簽名,以便該方法應該是一個完全覆蓋的方法,但是如何?
我有一些關於java中註釋工作的問題。編譯器如何處理註釋?
如果註釋不能轉換爲字節碼,那麼這些信息會去哪裏? 元數據在哪裏? Java Reflection如何使用此信息?
編譯器如何處理註釋?
當我們說,
@Override
public void doSomething(){
}
什麼是一個Java編譯器做呢?
我知道它檢查方法簽名,以便該方法應該是一個完全覆蓋的方法,但是如何?
有三種類型的註解見http://download.oracle.com/javase/6/docs/api/java/lang/annotation/RetentionPolicy.html
@Override是因爲編譯器做額外檢查的一個特例。
是否有可能看到編譯器處理'@ Override'註釋的代碼? – 2013-03-26 10:57:15
@NikolayKuznetsov是的,通過閱讀OpenJDK中'javac'的源代碼 – 2013-03-27 07:43:41
這個很簡單。編譯器只檢查超類,查找具有相同名稱和相同參數數量,它們的順序和類型的方法。如果方法有@Override
註釋,並且尚未找到此方法,則會生成錯誤。
更有趣的問題是編譯器如何處理在運行時具有意義的註釋。我假設它們是以字節碼形式添加的,但是在一些特殊的元信息部分。所以,在運行時jvm可以訪問meta部分。作爲證明,您始終可以在任何class
對象上致電getAnnotations()
。
@Override
是源類型的註釋 - 用於檢查是否一個特定的方法如下的覆蓋方法的合同 - 因此它不是在運行時可用(並且因此在邏輯上不存在於編譯的字節代碼存在)。
我知道它會檢查方法簽名,這樣的方法應該是一個完全重寫的方法,但如何
在閱讀的源文件,並將它們轉換成字節碼的過程中,例如,不根本不使用反射。有關其他編譯器信息,請參閱The Java Programming Language Compiler - javac。
註解e.g作爲public @interface @Override {}
實現@Override
具有RetentionPolicy,其可以允許所述註釋被存儲在一個類文件(RetentionPolicy.CLASS
,RetentionPolicy.RUNTIME
)或丟棄(RetentionPolicy.SOURCE
)。
@Override
方法的保留策略爲RetentionPolicy.SOURCE
,目標爲ElementType.METHOD
(意味着此方法只能在方法聲明上註釋)。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
PS如果你想反射性地讀取註釋,你將不得不在RetentionPolicy.RUNTIME
設置的RetentionPolicy。
起初,有兩種註釋:運行時可訪問(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就是很好的例子。編譯器插件可以使用自定義源代碼註釋,或者代碼是由其他代碼按需編譯的。
看看這是否有幫助http://pawanz.wordpress.com/2010/12/12/taming-java-annotations/ – ashishjmeshram 2011-03-25 12:54:20