一、注解是什么?
注釋大家都知道,就是對程式起解釋說明作用的,而注解同樣是對程式起解釋說明作用的,只不過注釋是給人看的,而注解是給計算機看的,
注解本質上是一個介面,該介面默認繼承Annotation介面,
二、預定義注解
預定義注解就是Java中已經定義好的注解,比如@Override,
幾個常用的預定義注解:
1.@Override:檢測該注解修飾的方法是否是繼承自父類(介面);
2.@Deprecated:表示該注解修飾的內容是已過時的;

3.@SuppressWarnings:壓制警告,忽略警告,一般傳遞引數“all”,@SuppressWarnings("all"),并且放在類上面,壓制整個類的所有警告,
也可以放在特定的位置指定要忽略的警告,@SuppressWarnings({"uncheck","指定警告"})
比如下圖,放在mid()方法上,壓制mid()方法中的已過時警告;

三、自定義注解和元注解
1.元注解
在Java中我們可以自己定義注解,在自定義注解時,需要涉及到元注解,元注解是什么呢?元注解就是用于描述注解的注解,
四種元注解:
1.@Target:用來描述注解能夠作用的位置,
(1) @Target(ElementType.TYPE):修飾的注解只能作用于類上
(2) @Target(ElementType.METHOD):修飾的注解只能作用于方法上
(3) @Target(ElementType.FIELD):修飾的注解只能作用于欄位上
注意:當注解未指定Target時,注解可以作用于任何元素上,多個值使用{ }包含并用都好隔開,如下:
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
2.@Retention:描述注解被保留的階段,用來約束注解的生命周期,
(1)@Rentention(RetentionPolicy.SOURCE):當前注解在原始碼編譯之前就會被編譯器拋棄(原始碼時期);
(2)@Rentention(RetentionPolicy.CLASS):當前注解可以保留到編譯期,在class檔案中可用,但在加載進記憶體之前就會被JVM丟棄(編譯時期);
(3)@Rentention(RetentionPolicy.RUNTIME):當前注解可以保留到運行期,即保留到class位元組碼檔案并可以被JVM讀取到,因此可以通過反射機制獲取到該注解的資訊(運行時期);
注意:當注解未指定Rentention值時,默認值是CLASS;
3.@Documented:描述注解是否被抽取到api檔案中,
示例:
定義兩個注解如下:
@Documented
public @interface MyAnno01 {
}
public @interface MyAnno02 {
}
在類中使用這兩個注解:
?
public class Anno01 {
public static void main(String[] args) {
@MyAnno01
@MyAnno02
public void big(){
System.out.println("Test...");
}
}
}
將上面java檔案(Anno01.java、MyAnno01.java、MyAnno02.java)放到一個檔案夾中,
win+R打開cmd,然后在cmd中打開上面這個java檔案所在檔案夾,輸入javadoc指令+空格+類名,如下:
C:\Users\Administrator\Desktop\xinjian>javadoc Anno01.java
之后回車即可生成api檔案,
在檔案中打開生成的index.html,可以發現

只有@MyAnno01注解被保留到api檔案中,而@MyAnno02注解則沒有,
4.@Inherited:可以讓注解被繼承,但這并不是真的繼承,只是通過使用@Inherited,可以讓子類Class物件使用getAnnotations()獲取父類被@Inherited修飾的注解,
當然,要通過此方法獲取注解資訊,@Inherited修飾的注解必須被@Rentention(RetentionPolicy.RUNTIME)修飾,
(注意:注解本身是不支持繼承的)
//定義注解
@Inherited
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnno01 {
}
//使用注解
@MyAnno01
class Mid{
}
//創建子類
class Small extends Mid{
}
public class Big {
public static void main(String[] args) {
Mid mid=new Small();
System.out.println(Arrays.toString(mid.getClass().getAnnotations()));
/*
運行結果:[@cn.Hello.MyAnno01()]
*/
}
}
2.自定義注解
自定義注解的格式為:
元注解
public @interface 注解名稱 {
屬性串列;
}
屬性串列:介面中可以定義的抽象方法,
要求:
屬性的回傳值型別有下列取值:
- 基本資料型別
- String
- 列舉
- 注解
- 以上型別的陣列
定義了屬性,在使用時需要給屬性賦值,
- 如果定義屬性時,使用default關鍵字給屬性值默認初始值,則使用注解時,可以不進行屬性的賦值;
- 如果只有一個屬性需要賦值,且該屬性名稱為value,則value可以省略,直接定義即可;
- 陣列賦值時,值使用{ }包裹,如果陣列只有一個值,則{ }可以省略,
比如:
@MyAnno01(num={1,2,3})
四、在程式中使用(決議)注解
在程式中使用(決議)注解:獲取注解中定義的屬性值,
步驟:
-
創建注解修飾元素的類物件;
-
用類物件呼叫getAnnotation()方法獲取注解物件;
-
呼叫注解中的抽象方法,獲取配置的屬性值,
案例如下:
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 Pro {
String className();
String methodName();
}
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
/*
創建一個“框架”類,可以創建任意類的物件,執行任意類中的方法
只需改動注解中的類名和方法名即可實作,
*/
@Pro(className = "cn._17_Annotation.Worker",methodName = "work")
public class ReflectTestPro {
public static void main(String[] args) throws Exception {
//決議注解:獲取注解中定義的屬性值
//1.創建注解修飾元素的類物件
Class<ReflectTestPro> proClass = ReflectTestPro.class;
//2.用類物件呼叫getAnnotation()方法獲取注解物件
Pro anno = proClass.getAnnotation(Pro.class);
//3.呼叫注解中的抽象方法,獲取配置的屬性值
String className = anno.className();
String methodName = anno.methodName();
//通過反射機制創建物件呼叫方法
Class cls = Class.forName(className);
Object obj = cls.newInstance();
Method method = cls.getMethod(methodName);
method.invoke(obj);
}
}
五、總結
注解是放在Java原始碼的類、方法、欄位、引數前的一種特殊“注釋”
注解的作用:
- 通過代碼里標識的注解生成幫助檔案;
- 通過代碼里標識的注解讓編譯器能夠實作基本的編譯檢查;(例如:@Override修飾的方法如果不是繼承自父類/介面,就會產生例外)
- 可以在反射中決議并使用Annotation,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/263798.html
標籤:java
