Java註解與註釋

JDK內置註解

@Override

@Override的作用是標記重寫父類的方法,@Override只能用於標記方法。編譯器編譯時會校驗使用@Override標記的方法是否與父類對應方法形式一致。例:

Man.java

public class Man{
    private String name;
    private float height;
    private int weight;
    public void setName(String name){};
    public void setHeight(float height){};
    public void setWeight(int weight){};
}

Woman.java

public class Woman extends Man{
    @Override
    public void setHeight(int height){
        //編譯時會報錯,因爲形參與父類不同
    }
}

@Deprecated

@Deprecated用於提示所修飾的元素(類、方法、變量等)已過時,繼續使用可能會發生危險或者存在更好的選擇。JDK更新過程中不會刪除過時的API,而是爲這些API加上@Deprecated標籤,使得JDK不建議用戶繼續使用該API的同時,也保證使用了過時API的舊項目能正常運行。

@SuppressWarnings

@SupressWarnings的作用是抑制編譯器警告。可以用於修飾所有成員。例如一個成員定義了卻未使用(unused),就可以使用@SupressWarnings("unused")來抑制成員未使用(unused)的警告。再例如使用原類型時抑制警告:

@SupressWarnings({"unused","rawtypes"})
ArrayList list = new ArrayList();   //使用了ArrayList不帶類型參數的原類型

元註解

概述

 元註解是用來修飾註解定義的註解。

@Retention

@Retention限定了被修飾註解的生命週期。它的取值有:

//註解在源文件(java文件)中有效(源文件保留),編譯時丟棄
@Retention(RetentionPolicy.SOURCE)        
//默認值。註解在class文件中有效(class保留),但不會加載到JVM
@Retention(RetentionPolicy.CLASS)  
//註解在運行時有效(運行時保留),JVM會保留註釋,所以程序運行時可以通過反射機制獲取到註解信息
@Retention(RetentionPolicy.RUNTIME)       

例:

@Retention(RetentionPolicy.SOURCE)
public @interface MyAnnotation{
    String[] value();
}

@Target

@Target指定被修飾註解可以用來修飾程序中的哪些元素。取值有:

TYPE:被修飾註解可以修飾class/interface/@interface/enum
FIELD:被修飾註解可以修飾field
METHOD:被修飾註解可以修飾method
PARAMETER:被修飾註解可以修飾parameter
CONSTRUCTOR:被修飾註解可以修飾constructor
LOCAL_VARIABLE:被修飾註解可以修飾local variable(局部變量)
ANNOTATION_TYPE:被修飾註解可以修飾Annotation type
PACKAGE:被修飾註解可以修飾package
TYPE_PARAMETER:被修飾註解可以修飾class parameter(泛型類型參數)
TYPE_USE:被修飾註解可以修飾任何使用的元素。

例:

@Target({TYPE,METHOD,CONSTRUCTOR})   //該註解可以用於修飾 類、方法、構造器
public @interface MyAnnotation{
    String[] value();
}

**注意:**若未指明@Target元註解,則該註解默認可以修飾程序中的所有元素。

@Documented

 被@Documented修飾的註解修飾的成員在API文檔中也會顯示出相應的註解,而默認API文檔中是不顯示註解的。

@Inherited

@Inherited修飾的註解將具有繼承性,即如果一個類被@Inherited修飾的註解修飾,這個類的子類將自動具有該註解。

自定義註解

使用@interface關鍵字定義註解:

public @interface MyAnnotation{
    /*
      成員變量以“無參方法”的形式聲明,“無參方法”的返回值即成員變量的值
    */
    int value();
    String message();
}

使用方法:

//修飾類
@MyAnnotation(value = 1,message = "type")
public class Person{
    //修飾屬性
    @MyAnnotation(value = 2,message = "field")
    private String name;
    //修飾構造器
    @MyAnnotation(value = 3,message = "constructor")
    public Person(String name){
        this.name = name;
    }
    //修飾方法
    @MyAnnotation(value = 4,message = "method")
    public String getName(){
        return name;
    }
    //修飾參數
    public void setName(@MyAnnotation(value = 5,message = "param") String name){
        this.name = name;
    }    
}

使用default關鍵字指定成員變量默認值:

public @interface MyAnnotation{
    int value() default 0;
    String message() default "";
}

此時再使用時可以不用帶參數從而直接使用默認值:

@MyAnnotation
public class Person{
    //也可以僅指定部分參數
    @MyAnnotation(message = "default test")
    public Person(String name){
        this.name = name;
    }
}

如果註解中沒有成員,這個註解就是一個標識。例如@Override

通過反射機制獲取RUNTIME註解

定義註解

MyAnnotation.java

@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnotation{
    int value() default 0;
    String message() default "";
}

Person

Person.java

@MyAnnotation(message = "Person")
public class Person{
    @MyAnnotation(value = 1,message = "name")
    private String name;
    @MyAnnotation(value = 2,message = "height")
    private float height;
    @MyAnnotation(value = 3,message = "weight")
    private int weight;
    
    @MyAnnotation(value = 4,message = "Person()")
    public Person(String name,float height,int weight){
        this.name = name;
        this.height = height;
        this.weight = weight;
    }
    
    @MyAnnotation(value = 5,message = "setName()")
    public void setName(@MyAnnotation(value = 6,message = "paramName")String name){
        this.name = name;      
    }
    @MyAnnotation(value = 7,message = "getName()")
    public String getName(){
        return name;
    }
    
    @MyAnnotation(value = 8,message = "setHeight()")
    public void setHeight(@MyAnnotation(value = 9,message = "paramHeight")float height){
        this.height = height;
    }
    @MyAnnotation(value = 10,message = "getHeight()")
    public float getHeight(){
        return height;
    }
    
    @MyAnnotation(value = 11,message = "setWeight()")
    public void setWeight(@MyAnnotation(value = 12,message = "paramWeight")int weight){
        this.weight = weight;
    }
    @MyAnnotation(value = 13,message = "getWeight()")
    public int getWeight(){
        return weight;
    }
    
}

獲取註解的方法

//java.lang.annotation.Annotation
public Annotation[] getAnnotations()
//java.lang.annotation.Annotation
public <A extends Annotation> A getAnnotation(Class<A> annotationClass)
//java.lang.annotation.Annotation
public Annotation[] getDeclaredAnnotations()
//java.lang.annotation.Annotation
public <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass)

獲取類的註解

Class<Person> clas = Person.class;
//獲取註解
MyAnnotation annotation = clas.getDeclaredAnnotation(MyAnnotation.class);
//獲取註解成員"value()"值
int value = annotation.value();
//獲取註解成員"message()"值
String message = annotation.message();
System.out.println("value:"+value+",message:"+message);

獲取屬性的註解

Class<Person> clas = Person.class;
//獲取屬性
Field name = clas.getDeclaredField("name");
//使可訪問
name.setAccessible(true);
//獲取註解
MyAnnotation annotation = name.getDeclaredAnnotation(MyAnnotation.class);
//獲取註解成員"value()"值
int value = annotation.value();
//獲取註解成員"message()"值
String message = annotation.message();
System.out.println("value:"+value+",message:"+message);

獲取構造器的註解

Class<Person> clas = Person.class;
//獲取構造器
Constructor<Person> cons =
    clas.getDeclaredConstructor(String.class,float.class,int.class);
//使可訪問
cons.setAccessible(true);
//獲取註解
MyAnnotation annotation = cons.getDeclaredAnnotation(MyAnnotation.class);
//獲取註解成員"value()"值
int value = annotation.value();
//獲取註解成員"message()"值
String message = annotation.message();
System.out.println("value:"+value+",message:"+message);

獲取方法的註解

Class<Person> clas = Person.class;
//獲取方法
Method method = clas.getDeclaredMethod("setName",String.class);
//使可訪問
method.setAccessible(true);
//獲取註解
MyAnnotation annotation = method.getDeclaredAnnotation(MyAnnotation.class);
//獲取註解成員"value()"值
int value = annotation.value();
//獲取註解成員"message()"值
String message = annotation.message();
System.out.println("value:"+value+",message:"+message);

獲取參數註解

Class<Person> clas = Person.class;
//獲取方法(或構造器)
Method method = clas.getDeclaredMethod("setHeight",float.class);
//使可訪問
method.setAccessible(true);
//獲取參數
Parameter param = (method.getParameters())[0];
//獲取註解
MyAnnotation annotation = param.getDeclaredAnnotation(MyAnnotation.class);
//獲取註解成員"value()"值
int value = annotation.value();
//獲取註解成員"message()"值
String message = annotation.message();
System.out.println("value:"+value+",message:"+message);

注意:

只有包含@Retention(RetentionPolicy.RUNTIME)修飾的註解才能使用反射機制獲取。

說明註釋

概述

 Java中有三種註釋形式:1.以//開頭的單行註釋;2.以/*開頭*/結尾的多行註釋;3.以/**開頭*/結尾的說明註釋

說明註釋允許在程序中嵌入對程序的說明信息,生成API文檔作爲API調用時的指導。

說明註釋中可以包含以@開頭標籤,用於對特定信息的描述,例如作者、版本、方法參數和方法返回值等。

常用的說明註釋標籤

1.@author:用於註釋。說明類的作者。例:

/**
*@author Lishaoyin
*/
public class Person{}

2.@version:用於註釋。說明類的版本。例:

/**
*@version 1.0
*/
public class Person{}

3.@since:用於類和任意類成員註釋。說明API是在JDK的哪個版本添加的。例:

/**
*@since 1.8
*/
public void setName(String name){}   //API在JDK1.8添加

4.@deprecated:用於類和任意類成員註釋。說明該類成員已過期,不建議使用。例:

/**
*@deprecated this field is deprecated,you can use better choice
*/
private String name;

5.@throws:用於方法和構造器註釋。說明方法或構造器可能會拋出的異常。例:

/**
*@throws java.io.IOException this method maybe throws IOException
*/
public void setHeight(float height) throws IOException {}

6.@exception:作用與@throws相同。

7.@see:用於類和任意類成員註釋。在生成的文檔中指定一個API文檔超鏈接,用戶點擊後可跳轉至指定內容的API文檔。例:

/**
*@see java.lang.annotation.Annotation
*/
public class Person{}

8.@param:用於方法和構造器註釋。說明方法或構造器的參數。例:

/**
*@param name String,person's name
*@param height float,person's height
*@param weight int,person's weight
*/
public Person(String name,float height,int weight){}

9.@return:用於方法註釋。說明方法的返回值。

/**
*@return String,person's name
*/
public String getName(){}

TODO

TODO是一種用法簡單的計劃標記工具,其作用是將計劃指示信息嵌入到註釋中(可嵌入到三種註釋中的任意一種)。編譯後可使用快速定位跳轉到指定計劃位置,繼續完成計劃中未完成的工作。例:

public class Person{
    
    public String getName(){
       //TODO function to get person's name 
    }
    
    public void setHeight(float height){
       /*TODO function to set person's height*/
    }
    
    /**
    *@param weight int,set person's weight
    *TODO function to set person's weight
    */
    public String setWeight(int weight){}
    
}

示例

Person.java

/**
*@author Lishaoyin
*version 1.0
*@since 1.8
*/
public class Person{
    
    private String name;
    private float height;
    private int weight;
    
    /**
    *@param name String,init person's name
    *@param height float,init person's height
    *@param weight int,init person's weight
    */
    public Person(String name,float height,int weight){
        this.name = name;
        this.height = height;
        this.weight = weight;
    }
    
    /**
    *@param name String,set person's name
    */
    public void setName(String name){
        this.name = name;
    } 
    /**
    *@return String,get person's name
    */
    public String getName(){
        return name;
    }
    
    /**
    *@param height float,set person's height
    */
    public void setHeight(float height){
        this.height = height;
    } 
    /**
    *@return float,get person's height
    */
    public float getHeight(){
        return height;
    }
    
    /**
    *@throws java.io.IOException this method maybe throws IOException
    *@see java.io.IOException
    *@param weight int,set person's weight
    */
    public void setWeight(int weight) throws java.io.IOException {
        this.weight = weight;
    }
    /**
    *@return int,get person's weight
    */
    public int getWeight(){
        return weight;
    }
    
    //TODO function to set person's sex
    
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章