1. 程式人生 > 程式設計 >Java註解使用及原理解析

Java註解使用及原理解析

基本特性

1、jdk 1.5之後才引入的。

2、用來說明程式的。(註釋是給程式設計師看的,註解就是給電腦看的)

java註解的作用分類

1、編寫文件:通過程式碼標識的註解生成文件。【生成doc文件】

2、程式碼分析:通過程式碼標識的註解對程式碼進行分析。【使用反射】

3、編譯檢查:通過程式碼標識的註解讓編譯器能夠實現基本的編譯檢查。【override】

測試類:

/**
 * 我的javadoc測試
 */
public class TestCode {
  /**
   * 計算兩個數的和
   * @param a 整數a
   * @param b 整數b
   * @return 返回兩個數的和
   */
  public int add(int a,int b){
    return a+b;
  }
}

對於2、3兩點我們應該是知道的。儘管可能不知道里面的原理。但是是平時都在用的。但是對於1點還可以生成doc文件?

測試操作如下:

D:\soft\jdk\bin\javadoc.exe .\TestCode.java -encoding utf-8 -docEncoding utf-8 -charset utf-8

生成了一大堆的東西:

Java註解使用及原理解析

開啟TestCode.html可以發現,我們的java api手冊就是這樣生產的。

註解來源分類

1、jdk自帶的註解,如常見的override(重寫校驗),deprecated(表示棄用)

2、自定義的註解

1)格式,以override為例:

Java註解使用及原理解析

2)註解的本質

我們編寫一個簡單的註解

MyAnnotation.java

public @interface MyAnnotation {}

我們通過編譯和反編譯看下最終是什麼樣的結果:

D:\soft\jdk\bin\javac.exe MyAnnotation.java

D:\soft\jdk\bin\javap.exe MyAnnotation.class

結果如下:

public interface MyAnnotation extends java.lang.annotation.Annotation {

}

可以發現註解的本質就是介面,這個介面繼承了jdk裡面的Annotation介面。

3)註解的屬性

由於註解本質為介面,那麼裡面可以定義未實現的方法。這些稱為註解的“屬性”。

屬性的返回型別有(返回值不能為void):

  • 基本資料型別
  • String
  • 列舉
  • 註解
  • 以及以上四種類型的陣列

例子:

public enum Person {
  PS;
}
public @interface Annotation2 {
}
public @interface MyAnnotation {
  String stringValue();
  int integerValue();
  Person personValue();
  Annotation2 myAnnotationValue();
  String[] stringArrayValue();
}

屬性的使用,需要注意幾點:

  • 定義了屬性在使用的時候就要給屬性賦值,除非設定default值。如:String stringValue() default "aaa";
  • 如果屬性為value且屬性只有這一個,那麼value可以省略,直接填寫屬性值。
  • 如果是陣列,需要用{}包含起來。
public @interface MyAnnotation {
  String stringValue() default "xxx";
  int integerValue();
  String[] stringArrayValue();
}

public @interface Annotation2 {
  String value();
}

@MyAnnotation(integerValue = 1,stringArrayValue = {"aaa","bbb"})
@Annotation2("default")
public class TestCode {
  /**
   * 計算兩個數的和
   * @param a 整數a
   * @param b 整數b
   * @return 返回兩個數的和
   */
  public int add(int a,int b){
    return a+b;
  }

  @Override
  public String toString() {
    return super.toString();
  }
}

元註解

元註解是你在編寫註解的時候,上面加的註解,就是註解的註解。主要有4個。

  • @target,用於指定註解的使用位置。如@Target(ElementType.ANNOTATION_TYPE),@Target(value = {ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})。
  • @Inherited,表示父類加了這個註解,子類也自動加上。
  • @Documented,表示這個註解的資訊在執行javadoc的時候是否抽取到api文件中。
  • @Retention,表示註解被保留的階段,java類,class檔案,以及被jvm讀取。總共三種。RetentionPolicy.SOURCE,RetentionPolicy.CLASS,RetentionPolicy.RUNTIME

元註解的內容,可以到jdk原始碼裡面看一下,更有利於理解。

解析註解

這個是最關鍵了,以上加了這麼多的屬性,並且還為這些屬性附了值,那麼是希望程式讀取這些值,進行使用的。那其實就是要看如何拿到這些註解配置的值。

測試:

MyAnnotition.java:

package annotation_;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
  String stringValue() default "xxx";
  int integerValue();
}

TestCode.java:

package annotation_;
@MyAnnotation(integerValue = 1)
public class TestCode {
  public static void main(String[] args) {
    Class<TestCode> testCodeClass = TestCode.class;
    MyAnnotation myAnnotation = testCodeClass.getAnnotation(MyAnnotation.class);
    int i = myAnnotation.integerValue();
    String s = myAnnotation.stringValue();
    System.out.printf("i = %d,s = %s\n",i,s);
  }
}

輸出結果:

Connected to the target VM,address: '127.0.0.1:49586',transport: 'socket'
i = 1,s = xxx
Disconnected from the target VM,transport: 'socket'

Process finished with exit code 0

是不是感覺可以當配置檔案使用。但是最主要的問題是myAnnotation.integerValue(),myAnnotation.stringValue()為什麼可以拿到對應的值,這個也是最核心的問題。

那就是getAnnotation裡面返回了一個實現了MyAnnotation註解(註解的本質是介面)的例項。這個類大概是長這樣的。

package annotation_;

import java.lang.annotation.Annotation;

public class MyAnnotationImpl implements MyAnnotation{
  public String stringValue() {
    return "xxx";
  }
  public int integerValue() {
    return 0;
  }
  public Class<? extends Annotation> annotationType() {
    return null;
  }
}

所以就可以通過抽象方法獲取到對應的值。(如何生成這樣的一個類,只是學習註解,可以不關心。要不然,只能看裡面的原始碼。因為如果自定義註解,你只會用到這一步,去獲取值。)

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。