Java註解最全詳解(超級詳細)

mikechen的網際網路架構發表於2022-08-16

Java註解是一個很重要的知識點,用於對程式碼進行說明,可以對包、類、介面、欄位、方法引數、區域性變數等進行註解。

掌握好Java註解有利於學習框架底層實現。@mikechen

Java註解定義

Java註解又稱Java標註,是在 JDK5 時引入的新特性,註解(也被稱為後設資料)。

Java註解它提供了一種安全的類似註釋的機制,用來將任何的資訊或後設資料(metadata)與程式元素(類、方法、成員變數等)進行關聯。

Java註解是附加在程式碼中的一些元資訊,用於一些工具在編譯、執行時進行解析和使用,起到說明、配置的功能。

 

Java註解應用

1.生成文件這是最常見的,也是java 最早提供的註解;

2.在編譯時進行格式檢查,如@Override放在方法前,如果你這個方法並不是覆蓋了超類方法,則編譯時就能檢查出;

3.跟蹤程式碼依賴性,實現替代配置檔案功能,比較常見的是spring 2.5 開始的基於註解配置,作用就是減少配置;

4.在反射的 Class, Method, Field 等函式中,有許多於 Annotation 相關的介面,可以在反射中解析並使用 Annotation。

 

Java註解分類

1、Java自帶的標準註解

包括@Override、@Deprecated、@SuppressWarnings等,使用這些註解後編譯器就會進行檢查。

2、元註解

元註解是用於定義註解的註解,包括@Retention、@Target、@Inherited、@Documented、@Repeatable 等。
元註解也是Java自帶的標準註解,只不過用於修飾註解,比較特殊。

3、自定義註解

使用者可以根據自己的需求定義註解。

 

Java標準註解

JDK 中內建了以下註解:

1.@Override

如果試圖使用 @Override 標記一個實際上並沒有覆寫父類的方法時,java 編譯器會告警。

class Parent {  public void test() {
  }
}class Child extends Parent  {   /**
         *  放開下面的註釋,編譯時會告警
         */
       /*
  @Override
  public void test() {
  }
*/}

2.Deprecated

@Deprecated 用於標明被修飾的類或類成員、類方法已經廢棄、過時,不建議使用。@Deprecatedclass TestClass {
  // do something}

3.@SuppressWarnings

@SuppressWarnings 用於關閉對類、方法、成員編譯時產生的特定警告。

1)抑制單型別的警告

@SuppressWarnings("unchecked")  public void addItems(String item){  
  @SuppressWarnings("rawtypes")  
   List items = new ArrayList();  
   items.add(item);  
}

2)抑制多型別的警告

@SuppressWarnings(value={"unchecked", "rawtypes"})  public void addItems(String item){  
   List items = new ArrayList();  
   items.add(item);  
}

3)抑制所有型別的警告

@SuppressWarnings("all")  public void addItems(String item){  
   List items = new ArrayList();  
   items.add(item);  
}

@SuppressWarnings 註解的常見引數值的簡單說明:

4.@FunctionalInterface

@FunctionalInterface 用於指示被修飾的介面是函式式介面,在 JDK8 引入。

@FunctionalInterfacepublic interface UserService {    void getUser(Long userId);    // 預設方法,可以用多個預設方法
    public default void setUser() {
    }    // 靜態方法
    public static void saveUser() {
    }    
    // 覆蓋Object中的equals方法
    public boolean equals(Object obj);}

函式式介面(Functional Interface)就是一個有且僅有一個抽象方法,但是可以有多個非抽象方法的介面。

Java元註解

元註解是java API提供的,是用於修飾註解的註解,通常用在註解的定義上:

1.@Retention

@ Retention用來定義該註解在哪一個級別可用,在原始碼中(SOURCE)、類檔案中(CLASS)或者執行時(RUNTIME)。

@Retention 原始碼:

@Documented@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
  RetentionPolicy value();
}public enum RetentionPolicy {
  //此註解型別的資訊只會記錄在原始檔中,編譯時將被編譯器丟棄,也就是說  //不會儲存在編譯好的類資訊中  SOURCE,
  //編譯器將註解記錄在類檔案中,但不會載入到JVM中。如果一個註解宣告沒指定範圍,則系統  //預設值就是Class  CLASS,
  //註解資訊會保留在原始檔、類檔案中,在執行的時也載入到Java的JVM中,因此可以反射性的讀取。  RUNTIME}

RetentionPolicy 是一個列舉型別,它定義了被 @Retention 修飾的註解所支援的保留級別:

@Target(ElementType.METHOD)@Retention(RetentionPolicy.SOURCE) //註解資訊只能在原始檔中出現public @interface Override {
}@Documented@Retention(RetentionPolicy.RUNTIME)  //註解資訊在執行時出現@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})public @interface Deprecated {
}@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})@Retention(RetentionPolicy.SOURCE)  //註解資訊在原始檔中出現public @interface SuppressWarnings {  String[] value();
}

2.@Documented

@Documented:生成文件資訊的時候保留註解,對類作輔助說明

@Documented 示例

@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface Column {
    public String name() default "fieldName";
    public String setFuncName() default "setField";
    public String getFuncName() default "getField";
    public boolean defaultDBValue() default false;
}

3.@Target

@Target:用於描述註解的使用範圍(即:被描述的註解可以用在什麼地方)

@Target原始碼:

@Documented@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    ElementType[] value();
}

ElementType 是一個列舉型別,它定義了被 @Target 修飾的註解可以應用的範圍:

4.@Inherited

@Inherited:說明子類可以繼承父類中的該註解

表示自動繼承註解型別。 如果註解型別宣告中存在 @Inherited 元註解,則註解所修飾類的所有子類都將會繼承此註解。

@Inheritedpublic @interface Greeting {
    public enum FontColor{ BULE,RED,GREEN};
    String name();
    FontColor fontColor() default FontColor.GREEN;
}

5.@Repeatable

@Repeatable 表示註解可以重複使用。

當我們需要重複使用某個註解時,希望利用相同的註解來表現所有的形式時,我們可以藉助@Repeatable註解。
以 Spring @Scheduled 為例:

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface Schedules {
    Scheduled[] value();
}
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented@Repeatable(Schedules.class)public @interface Scheduled {
  // ...}

自定義註解

當我們理解了內建註解, 元註解和獲取註解的反射介面後,我們便可以開始自定義註解了。

建立自定義註解和建立一個介面相似,但是註解的interface關鍵字需要以@符號開頭,我們可以為註解宣告方法。

自定義註解格式:

// 元註解public @interface 註解名稱{    // 屬性列表}

我們先來看看註解的例子:

1.建立自定義註解

/**
 * 自定義註解例子
 *
 * @author mikechen
 */@Documented@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)@Inheritedpublic @interface HelloAnnotation {    String value();
}

 

2.使用自定義註解

/**
 * 使用自定義註解
 *
 * @author mikechen
 */public class HelloAnnotationClient {
    @HelloAnnotation(value="Simple custom Annotation example")    public void sayHello(){
        System.out.println("Inside sayHello method..");
    }
}

3.測試自定義註解

/**
 * 自定義註解測試
 *
 * @author mikechen
 */public class HelloAnnotationTest {    public static void main(String[] args) throws Exception {
        HelloAnnotationClient helloAnnotationClient=new HelloAnnotationClient();
        Method method=helloAnnotationClient.getClass().getMethod("sayHello");        if(method.isAnnotationPresent(HelloAnnotation.class)){
            HelloAnnotation helloAnnotation=method.getAnnotation(HelloAnnotation.class);            //Get value of custom annotation
            System.out.println("Value : "+helloAnnotation.value());            //Invoke sayHello method
            method.invoke(helloAnnotationClient); }
            }
}

以上

我是 mikechen,10年+大廠架構經驗,曾就職阿里、淘寶、百度,分享架構技術經驗以及心得!

關注公眾號 mikechen的網際網路架構 回覆【架構】,即可領取我原創的《300期+BAT架構技術系列與1000+大廠面試題答案合集》。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70011997/viewspace-2882762/,如需轉載,請註明出處,否則將追究法律責任。

相關文章