Java工作笔记-注解的进一步理解
目錄
?
?
基本概念
代碼與實(shí)例
?
基本概念
注解:說(shuō)明程序,給計(jì)算機(jī)看的。
注釋:給程序員看的。
?
作用分類:
編寫文檔:通過(guò)代碼里標(biāo)識(shí)的注解生成文檔javadoc(生成doc文檔)
代碼分析:通過(guò)代碼里標(biāo)識(shí)的注解對(duì)代碼進(jìn)行分析(使用反射)
編譯檢查:通過(guò)代碼里標(biāo)識(shí)的注解人編譯器能夠?qū)崿F(xiàn)基本的編譯檢測(cè)(Override)
?
JDK中預(yù)定義的注解:
@Override:檢測(cè)被該注釋標(biāo)注的方法是否繼承自父類(接口)
@Deprecated:該注解標(biāo)注的內(nèi)容,已經(jīng)過(guò)時(shí)
@SuppressWarnings:壓制警告
?
這里提示下:@SuppressWarnings("all")一般是這么用的
?
代碼與實(shí)例
下面來(lái)看下自定義注解,格式如下:
元注解
public @interface 注解名稱{}
注解的本質(zhì),實(shí)際上是接口:
如下代碼:
package demo;public @interface AnnoDemo1 {}目前先使用javac讓其生成字節(jié)碼文件,再使用javap逆向生成類:
從中可以看到注解的本質(zhì)就是接口.
注解(接口)中的屬性:
? ? ? ? ? 要求:
? ? ? ? ? 1. 屬性的返回值類型:基本數(shù)據(jù)類型、String、枚舉、注解、以上類型的數(shù)組;
? ? ? ? ? 2. 定義了屬性,在使用時(shí)需要給屬性賦值;
? ? ? ? ? ? ?1. 如果定義屬性時(shí),使用default關(guān)鍵字給屬性設(shè)置默認(rèn)值,則使用注解時(shí),可以不進(jìn)行屬性的賦值。
? ? ? ? ? ? ?2. 如果只有一個(gè)屬性需要賦值,并且屬性的名稱是value,則value可以省略,直接定義即可。
? ? ? ? ? ? ?3. 數(shù)組賦值時(shí),值使用{}包裹。如果數(shù)組中只有一個(gè)值,則{}省略
如下代碼:
Person.java
package demo;public enum Person {p1, p2 }AnnoDemo1.java
package demo;public @interface AnnoDemo1 {int show1();String show2();Person per();AnnoDemo2 anno2();String[] strs();}AnnoDemo2.java
package demo;public @interface AnnoDemo2 {int age();String name() default "王二麻子";}Worker.java
package demo;@AnnoDemo1(show1 = 1, show2 = "Hello", per = Person.p1, anno2 = @AnnoDemo2(age = 12), strs = {"1", "2"}) public class Worker { }下面是關(guān)于元注解相關(guān):
元注解:
? ? ? ? ? @Target:描述注解能夠作用的位置;
? ? ? ? ? ? ? ? ? ? ElementTYpe取值:
? ? ? ? ? ? ? ? ? ? ? ? ?TYPE:可以作用于類上
? ? ? ? ? ? ? ? ? ? ? ? ?METHOD:作用于方法上
? ? ? ? ? ? ? ? ? ? ? ? ?FIELD:用于成員變量
? ? ? ? ? @Retention:描述注解被保留的階段;
? ? ? ? ? ? ? ? ? ? ?@Retention(RetentionPolicy.RUNTIME):保留class字節(jié)碼文件中,并被JVM讀取。
? ? ? ? ? @Decumented:描述注解是否被抽到API文檔中;
? ? ? ? ? @Inherited:描述注解是否被子類繼承。
這里要注意:自定義注解一般使用runtime
后期注解大多數(shù)都是用于替換配置文件的
如下:
AnnoDemo3.java
package demo;import java.lang.annotation.*;@Target(value = {ElementType.METHOD, ElementType.FIELD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited public @interface AnnoDemo3 {}注解中:
package demo;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(); }這個(gè)注解,實(shí)際上會(huì)生成這樣的字節(jié)碼文件,這個(gè)個(gè)人感覺(jué)和Qt中帶有Q_OBJECT和集成了QObject類,生成moc的技術(shù)有異曲同工之妙。
public class ProImpl implements Pro{public String className(){}public String methodName(){} }?
下面是使用注解來(lái)實(shí)現(xiàn)配置文件的加載
如下的例子:
Pro.java
package demo;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(); }MainTest.java
import demo.Pro;import java.lang.reflect.Method;@Pro(className = "demo.Test", methodName = "show") public class MainTest {public static void main(String[] arg) throws Exception{//解析注釋,獲取該類的字節(jié)碼文件對(duì)象Class mainTestClass = MainTest.class;//獲取注解對(duì)象,內(nèi)存中生成了一個(gè)該注解接口的子類實(shí)例Pro annotation = (Pro) mainTestClass.getAnnotation(Pro.class);//調(diào)用抽象方法,獲取數(shù)據(jù)String s = annotation.className();String s1 = annotation.methodName();//加載該類進(jìn)內(nèi)存Class aClass = Class.forName(s);//創(chuàng)建對(duì)象Object o = aClass.newInstance();//獲取方法對(duì)象Method method = aClass.getMethod(s1);//執(zhí)行方法method.invoke(o);} }在程序使用(解析)注解:獲取注解中定義的屬性值:
? ? ?1. 獲取注解定義的位置的對(duì)象(Class,Method,Field)
? ? ?2. 獲取指定的注解:
? ? ? ? ? ? getAnnotation(Class)
? ? ?3. 調(diào)用注解中的抽象方法獲取配置的屬性值。
?
下面是一個(gè)綜合案例,通過(guò)注解完成,某個(gè)函數(shù)的測(cè)試功能。
統(tǒng)計(jì)一個(gè)類中,不拋異常的函數(shù)個(gè)數(shù):
程序運(yùn)行截圖如下:
錯(cuò)誤文件:
源碼如下:
Calculator.java
package demo2;public class Calculator {@Checkpublic void add(){System.out.println("1 + 0 = " + (1 + 0));}@Checkpublic void sub(){System.out.println("1 - 0 = " + (1 - 0));}@Checkpublic void mul(){System.out.println("1 * 0 = " + (1 * 0));}@Checkpublic void div(){System.out.println("1 / 0 = " + (1 / 0));} }Check.java
package demo2;import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Check {}MainTest2.java
import demo2.Calculator; import demo2.Check;import java.io.BufferedWriter; import java.io.FileWriter; import java.lang.reflect.Method;public class MainTest2 {public static void main(String[] arg) throws Exception{//創(chuàng)建計(jì)算器對(duì)象Calculator c = new Calculator();//獲取字節(jié)碼文件對(duì)象Class cls = c.getClass();//獲取所有方法Method[] methods = cls.getMethods();int number = 0;//出現(xiàn)異常的此數(shù)BufferedWriter bw = new BufferedWriter(new FileWriter("bug.txt"));for(Method method : methods){//判斷方法上是否有Check注解if(method.isAnnotationPresent(Check.class)){//有就執(zhí)行try{method.invoke(c);}catch (Exception e){//獲取異常,記錄到文件number++;bw.write(method.getName() + "方法出現(xiàn)異常");bw.newLine();bw.write("異常名稱:" + e.getCause().getClass().getSimpleName());bw.newLine();bw.write("異常原因:" + e.getCause().getMessage());bw.newLine();bw.write("------------------------------");}}}bw.newLine();bw.write("本次測(cè)試一共出現(xiàn) " + number + " 次異常");bw.flush();bw.close();} }注解不是程序的一部分,是給編譯器看的,可以理解為注解是一個(gè)標(biāo)簽。
源碼打包下載地址:https://github.com/fengfanchen/Java/tree/master/Annotation
?
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的Java工作笔记-注解的进一步理解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 视频课程-1小时上手 Spring Bo
- 下一篇: C语言工作笔记-对函数指针的进一步认识(