Java注解使用及原理解析
基本特性
1、jdk 1.5之后才引入的。
2、用來說明程序的。(注釋是給程序員看的,注解就是給電腦看的)
java注解的作用分類
1、編寫文檔:通過代碼標(biāo)識的注解生成文檔?!旧蒬oc文檔】
2、代碼分析:通過代碼標(biāo)識的注解對代碼進(jìn)行分析?!臼褂梅瓷洹?/p>
3、編譯檢查:通過代碼標(biāo)識的注解讓編譯器能夠?qū)崿F(xiàn)基本的編譯檢查?!緊verride】
測試類:
/**
* 我的javadoc測試
*/
public class TestCode {
/**
* 計(jì)算兩個數(shù)的和
* @param a 整數(shù)a
* @param b 整數(shù)b
* @return 返回兩個數(shù)的和
*/
public int add(int a, int b){
return a+b;
}
}
對于2、3兩點(diǎn)我們應(yīng)該是知道的。盡管可能不知道里面的原理。但是是平時都在用的。但是對于1點(diǎn)還可以生成doc文檔?
測試操作如下:
D:\soft\jdk\bin\javadoc.exe .\TestCode.java -encoding utf-8 -docEncoding utf-8 -charset utf-8
生成了一大堆的東西:

打開TestCode.html可以發(fā)現(xiàn),我們的java api手冊就是這樣生產(chǎn)的。
注解來源分類
1、jdk自帶的注解,如常見的override(重寫校驗(yàn)),deprecated(表示棄用)
2、自定義的注解
1)格式, 以override為例:

2)注解的本質(zhì)
我們編寫一個簡單的注解
MyAnnotation.java
public @interface MyAnnotation {}
我們通過編譯和反編譯看下最終是什么樣的結(jié)果:
D:\soft\jdk\bin\javac.exe MyAnnotation.java
D:\soft\jdk\bin\javap.exe MyAnnotation.class
結(jié)果如下:
public interface MyAnnotation extends java.lang.annotation.Annotation {
}
可以發(fā)現(xiàn)注解的本質(zhì)就是接口,這個接口繼承了jdk里面的Annotation接口。
3)注解的屬性
由于注解本質(zhì)為接口,那么里面可以定義未實(shí)現(xiàn)的方法。這些稱為注解的“屬性”。
屬性的返回類型有(返回值不能為void):
- 基本數(shù)據(jù)類型
- String
- 枚舉
- 注解
- 以及以上四種類型的數(shù)組
例子:
public enum Person {
PS;
}
public @interface Annotation2 {
}
public @interface MyAnnotation {
String stringValue();
int integerValue();
Person personValue();
Annotation2 myAnnotationValue();
String[] stringArrayValue();
}
屬性的使用,需要注意幾點(diǎn):
- 定義了屬性在使用的時候就要給屬性賦值,除非設(shè)置default值。如:String stringValue() default "aaa";
- 如果屬性為value且屬性只有這一個,那么value可以省略,直接填寫屬性值。
- 如果是數(shù)組,需要用{}包含起來。
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 {
/**
* 計(jì)算兩個數(shù)的和
* @param a 整數(shù)a
* @param b 整數(shù)b
* @return 返回兩個數(shù)的和
*/
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, 表示這個注解的信息在執(zhí)行javadoc的時候是否抽取到api文檔中。
- @Retention,表示注解被保留的階段,java類,class文件,以及被jvm讀取??偣踩N。RetentionPolicy.SOURCE, RetentionPolicy.CLASS, RetentionPolicy.RUNTIME
元注解的內(nèi)容,可以到j(luò)dk源碼里面看一下,更有利于理解。
解析注解
這個是最關(guān)鍵了,以上加了這么多的屬性,并且還為這些屬性附了值,那么是希望程序讀取這些值,進(jìn)行使用的。那其實(shí)就是要看如何拿到這些注解配置的值。
測試:
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);
}
}
輸出結(jié)果:
Connected to the target VM, address: '127.0.0.1:49586', transport: 'socket'
i = 1, s = xxx
Disconnected from the target VM, address: '127.0.0.1:49586', transport: 'socket'Process finished with exit code 0
是不是感覺可以當(dāng)配置文件使用。但是最主要的問題是myAnnotation.integerValue(),myAnnotation.stringValue()為什么可以拿到對應(yīng)的值,這個也是最核心的問題。
那就是getAnnotation里面返回了一個實(shí)現(xiàn)了MyAnnotation注解(注解的本質(zhì)是接口)的實(shí)例。這個類大概是長這樣的。
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;
}
}
所以就可以通過抽象方法獲取到對應(yīng)的值。(如何生成這樣的一個類,只是學(xué)習(xí)注解,可以不關(guān)心。要不然,只能看里面的源碼。因?yàn)槿绻远x注解,你只會用到這一步,去獲取值。)
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
java?HttpURLConnection類的disconnect方法與http長連接詳解
這篇文章主要介紹了java?HttpURLConnection類的disconnect方法與http長連接,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-04-04
Java 使用keytool創(chuàng)建CA證書的操作
這篇文章主要介紹了Java 使用keytool創(chuàng)建CA證書的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-01-01
淺談springboot內(nèi)置tomcat和外部獨(dú)立部署tomcat的區(qū)別
這篇文章主要介紹了淺談springboot內(nèi)置tomcat和外部獨(dú)立部署tomcat的區(qū)別,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-10-10
Spring實(shí)現(xiàn)源碼下載編譯及導(dǎo)入IDEA過程圖解
這篇文章主要介紹了Spring實(shí)現(xiàn)源碼下載編譯及導(dǎo)入IDEA,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-07-07
Springboot 跨域配置無效及接口訪問報(bào)錯的解決方法
這篇文章主要介紹了Springboot 跨域配置無效及接口訪問報(bào)錯的解決方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-12-12
Java生成隨機(jī)姓名、性別和年齡的實(shí)現(xiàn)示例
這篇文章主要介紹了Java生成隨機(jī)姓名、性別和年齡的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09

