常常在代碼中看到註解,經常使用的有@Override、@Deprecated、Spring註解。html
@Override代碼以下:java
package java.lang; import java.lang.annotation.*; @Target(ElementType.METHOD) @Retention(RetentionPolicy.SOURCE) public @interface Override { }
Override裏面很乾淨,什麼都沒有,可是外面有。編程
涉及到了兩個元註解:api
@Target :顧名思義,說明@Override能夠用來註解方法。oracle
@Retention:定義該註解的生命週期,默認爲RetentionPolicy.CLASS。jvm
類型 | 使用場景 | 常見例子 |
RetentionPolicy.SOURCE | 在編譯階段丟棄。這些註解在編譯結束以後就再也不有任何意義,因此它們不會寫入字節碼。 | @Override, @SuppressWarnings都屬於這類註解。 |
RetentionPolicy.CLASS | 在類加載的時候丟棄。在字節碼文件的處理中有用。註解默認使用這種方式。 | |
RetentionPolicy.RUNTIME | 始終不會丟棄,運行期也保留該註解,所以可使用反射機制讀取該註解的信息。 | 咱們自定義的註解一般使用這種方式。 |
查api doc,看到還有另外兩種元註解:ide
@Documented:註解是否將包含在JavaDoc中函數
@Inherited:是否容許子類繼承該註解spa
另外,還發現了一個Annotation接口:.net
package java.lang.annotation; public interface Annotation { boolean equals(Object obj); int hashCode(); Class<? extends Annotation> annotationType(); }
此接口功能以下(雖然有點繞,可是說的仍是挺清楚地):
一、任何註解都繼承了此接口;
二、經過 xxInterface extends Annotation方式繼承的不聲明註解;
三、此接口本身沒有聲明註解。
從這個知乎問題知道,註解反編譯以後實際上繼承了Annotation。
言歸正傳,看過了@Override的代碼,會產生2個疑問:
一、@Override的功能(檢查在父類中有一個相同簽名的函數)是誰來完成的?
二、如何自定義一個註解?
咱們先說第二個問題~
1、如何自定義一個Annotation?
簡單如@Retention,發現Retention能夠本身註解本身,這不算犯規。
package java.lang.annotation; @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface Retention { RetentionPolicy value(); }
自定義代碼(引自refer2連接):
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface TestAnnotation { int count() default 1; // 默認是public,default不是必須的,方法必須有返回值; } @TestAnnotation(count = 0x7fffffff) public class TestMain { public static void main(String[] args) throws InterruptedException, NoSuchFieldException, IllegalAccessException, IOException { TestAnnotation annotation = TestMain.class.getAnnotation(TestAnnotation.class); System.out.println(annotation.count()); System.in.read(); } }
refer3裏有個Filed的例子,這個博客被轉的還蠻多的。
2、@Override的功能是誰來完成的?
如今的java IDE都是自動編譯的,編譯的時候就能夠檢查是否正確的Override了父類的方法了~
PS: JVM是如何選擇@Override的方法的?
看了一些博客以後,大概明白了。因爲繼承的存在,變量具備「靜態類型」和「實際類型」,靜態類型在編譯器肯定,實際類型在運行期肯定,執行的時候調用實際類型的Override的方法便可。
Override和Overload的底層實現叫作「分派」(原諒本身第一次見到這個詞)。發現Override是jvm的一個叫「動態分派」的過程完成的,與之相對的靜態分派是重載(Overload)。除此以外還有多分派、單分派這對術語。
3、相關問題
一、Spring中使用註解註冊Bean;
refer: