什么是注解?
當我們開發(fā)SpringBoot項目,我們只需對啟動類加上@SpringBootApplication
,就能自動裝配,不需要編寫冗余的xml配置。當我們?yōu)轫椖刻砑觢ombok依賴,使用@Data
來修飾實體類,我們就不需要編寫getter和setter方法,構(gòu)造函數(shù)
等等。@SpringBootApplication,@Data等
像這種以**"@"**
開頭的代碼 就是 注解, 只需簡簡單單幾個注解,就能幫助我們省略大量冗余的代碼,這是一個非常不可思議的事情!
但我們往往知道在哪些地方加上合適的注解,不然IDE會報錯,卻不知道其中的原理,那究竟什么是注解呢?
注解(Annotation ), 是 Java5 開始引入的新特性,是放在Java源碼的類、方法、字段、參數(shù)前的一種特殊“注釋”, 是一種標記、標簽。 注釋往往會被編譯器直接忽略,能夠被編譯器打包進入class文件,并執(zhí)行相應(yīng)的處理。
按照慣例我們?nèi)タ聪伦⒔獾脑创a:
先新建一個注解文件:MyAnnotation.java
public @interface MyAnnotation {
}
發(fā)現(xiàn)MyAnnotation 是被@interface
修飾的,感覺和接口interface
很像。
我們再通過idea來看下其的類繼承:
MyAnnotation 是繼承Annotation接口的。
我們再反編譯一下:
$ javac MyAnnotation.java
$ javap -c MyAnnotation
Compiled from "MyAnnotation.java"
public interface com.zj.ideaprojects.test3.MyAnnotation extends java.lang.annotation.Annotation {
}
發(fā)現(xiàn)生成的字節(jié)碼中 @interface變成了interface,MyAnnotation而且自動繼承了Annotation
我們由此可以明白:注解本質(zhì)是一個繼承了Annotation 的特殊接口, 所以注解也叫聲明式接口
注解的分類
一般常用的注解可以分為三大類:
Java自帶的標準注解
例如:
元注解
元注解是能夠用于定義注解的注解, 或者說元注解是一種基本注解,包括@Retention、@Target、@Inherited、@Documented、@Repeatable 等
元注解也是Java自帶的標準注解,只不過用于修飾注解
,比較特殊。
@Retention
注解的保留策略, @Retention 定義了Annotation的生命周期 。當 @Retention 應(yīng)用到一個注解上的時候,它解釋說明了這個注解的的存活時間。
它的參數(shù):
RetentionPolicy.SOURCE | 注解只在源碼階段保留,在編譯器進行編譯時它將被丟掉 |
---|---|
RetentionPolicy.CLASS | 注解只被保留到編譯進行的時候,它并不會被加載到 JVM 中 |
RetentionPolicy.RUNTIME | 注解可以保留到程序運行中的時候,它會被加載進 JVM中,在程序運行中也可以獲取到它們 |
如果@Retention不存在,則該Annotation默認為RetentionPolicy.CLASS
示例:
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
}
我們自定義的TestAnnotation 可以在程序運行中被獲取到
@Documented
它的作用是 用于 制作文檔 ,將注解中的元素包含到 doc 中
一般不怎么用到,了解即可
@Target
@Target 指定了注解可以修飾哪些地方 , 比如方法、成員變量、還是包等等
當一個注解被 @Target 注解時,這個注解就被限定了運用的場景。
常用的參數(shù)如下:
ElementType.ANNOTATION_TYPE | 給一個注解進行注解 |
---|---|
ElementType.CONSTRUCTOR | 給構(gòu)造方法進行注解 |
ElementType.FIELD | 給屬性進行注解 |
ElementType.LOCAL_VARIABLE | 給局部變量進行注解 |
ElementType.METHOD | 給方法進行注解 |
ElementType.PACKAGE | 給包進行注解 |
ElementType.PARAMETER | 給一個方法內(nèi)的參數(shù)進行注解 |
ElementType.TYPE | 給一個類型進行注解,比如類、接口、枚舉 |
@Inherited
@Inherited 修飾一個類時,表明它的注解可以被其子類 繼承 ,缺省情況默認是不繼承的。
換句話說:如果一個子類想獲取到父類上的注解信息,那么必須在父類上使用的注解上面 加上@Inherit關(guān)鍵字
注意:
- @Inherited僅針對@Target(ElementType.TYPE)類型的annotation有效
- @Inherited 不是表明 注解可以繼承,而是子類可以繼承父類的注解
我們來看一個示例:
定義一個注解:
@Inherited
@Target(ElementType.TYPE)
public @interface MyReport {
String name() default "";
int value() default 0;
}
使用這個注解:
@MyReport(value=1)
public class Teacher {
}
則它的子類默認繼承了該注解:
public class Student extends Teacher{
}
idea 查看類的繼承關(guān)系:
【圖重截】
@Repeatable
使用@Repeatable這個元注解來申明注解,表示這個聲明的注解是可重復的
@Repeatable 是 Java 1.8 才加進來的,所以算是一個新的特性。
比如:一個人他既會下棋又會做飯,他還會唱歌。
@Repeatable(MyReport.class)
@Target(ElementType.TYPE)
public @interface MyReport {
String name() default "";
int value() default 0;
}
@MyReport(value=0)
@MyReport(value=1)
@MyReport(value=2)
public class Man{
}
自定義注解
我們可以根據(jù)自己的需求定義注解,一般分為以下幾步:
- 新建注解文件, @interface定義注解
public @interface MyReport { }
- 添加參數(shù)、默認值
public @interface MyReport {
String name() default "";
int value() default 0;
}
- 用元注解配置注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyReport {
String name() default "";
int value() default 0;
}
我們一般設(shè)置 @Target和@Retention就夠了,其中@Retention一般設(shè)置為RUNTIME,因為我們自定義的注解通常需要在程序運行中讀取。
自定義注解的讀取
讀到這里,相信大家已經(jīng)明白了 如何定義
和使用注解
,我們接下來 就需要如何將注解利用起來。
我們知道讀取注解, 需要用到j(luò)ava的反射
推薦閱讀筆者之前寫過關(guān)于反射的文章:https://mp.weixin.qq.com/s/_n8HTIjkw7Emcunpb4-Iwg
我們先來寫一個簡單的示例-- 反射獲取注解 :
通過前文的了解,先來改造一下MyAnnotation.java
@Retention(RetentionPolicy.RUNTIME)//確保程序運行中,能夠讀取到該注解!!!
public @interface MyAnnotation {
String msg() default "no msg";
}
我們再用@MyAnnotation
來修飾Person類的類名、屬性、和方法
@MyAnnotation(msg = "this person class")//注解 修飾類
public class Person {
private String name;//姓名
private String sex;//性別
@MyAnnotation(msg = "this person field public")//注解 修飾 public屬性
public int height;//身高
@MyAnnotation(msg = "this person field private")//注解 修飾 private屬性
private int weight;//體重
public void sleep(){
System.out.println(this.name+"--"+ "睡覺");
}
public void eat(){
System.out.println("吃飯");
}
@MyAnnotation(msg = "this person method")//注解 修飾方法
public void dance(){
System.out.println("跳舞");
}
}
-
JAVA
+關(guān)注
關(guān)注
19文章
2974瀏覽量
104986 -
XML
+關(guān)注
關(guān)注
0文章
188瀏覽量
33112 -
spring
+關(guān)注
關(guān)注
0文章
340瀏覽量
14369
發(fā)布評論請先 登錄
相關(guān)推薦
評論