前言
在你立足處深挖下去,就會(huì)有泉水涌出!別管蒙昧者們叫嚷:“下邊永遠(yuǎn)是地獄!”
博客主頁:KC老衲愛尼姑的博客主頁
博主的github,平常所寫代碼皆在于此
共勉:talk is cheap, show me the code
作者是爪哇島的新手,水平很有限,如果發(fā)現(xiàn)錯(cuò)誤,一定要及時(shí)告知作者哦!感謝感謝!
注解
概述
Java注解是Java5引入的一種注釋解釋,又稱之為標(biāo)注。Java中的類,構(gòu)造器,方法,成員變量,參數(shù)等都可以被注解進(jìn)行標(biāo)注。我們可以將注解理解為標(biāo)簽,標(biāo)簽可以上的內(nèi)容可以自由的定義,它是對(duì)人和事物屬性的評(píng)價(jià)。這就如商品上的價(jià)格標(biāo)簽,圖書館中的書本編碼標(biāo)簽,B站上游戲分區(qū)標(biāo)簽等。
注解的作用
對(duì)Java中類,方法,成員變量做標(biāo)記,然后進(jìn)行特殊處理,至于到底進(jìn)行何種處理由具體業(yè)務(wù)決定。比如說:JUnit框架中,標(biāo)注了注解為@Test的方法就可以被當(dāng)成測(cè)試方法執(zhí)行,而沒有標(biāo)記的就不能打算當(dāng)初當(dāng)成測(cè)試方法執(zhí)行。
特殊屬性
- value屬性,如果只有一個(gè)value屬性的情況下,使用value屬性的時(shí)候可以省略value名稱不寫。
- 但是如果有多個(gè)屬性,并且屬性沒有默認(rèn)值,那么value名稱不能省略。
自定義注解格式
public @interface 注解名稱 {
? public 屬性類型 屬性名() default 默認(rèn)值;
}
代碼示例
public @interface MyDemo {
String value();
String name();
boolean flag() default true;
String [] str();
}
元注解
元注解就是注解的注解,注解的標(biāo)簽。
常用的元注解
- @Target: 約束自定義注解只能在哪些地方使用
- @Retention:申明注解的生命周期
@Target中可使用的值定義在枚舉類ElementType中,常用值如下:
- TYPE,類
- 接口 FIELD,
- 成員變量METHOD,
- 成員方法PARAMETER,
- 方法參數(shù)CONSTRUCTOR,
- 構(gòu)造器LOCAL_VARIABLE
- 局部變量
@Retention中可使用的值定義在枚舉類ElementType中,常用值如下:
- SOURCE: 注解只作用在源碼階段,生成的字節(jié)碼文件中不存在
- CLASS: 注解作用在源碼階段,字節(jié)碼文件階段,運(yùn)行階段不存在,默認(rèn)值.
- RUNTIME:注解作用在源碼階段,字節(jié)碼文件階段,運(yùn)行階段(開發(fā)常用)
注解的解析
示例代碼
@Target({ElementType.TYPE,ElementType.METHOD})// 當(dāng)前被修飾的注解只能用在類上,方法上。
@Retention(RetentionPolicy.RUNTIME)// 控制下面的注解一直保留到運(yùn)行時(shí)
public @interface MyTest {
}
MyTest的使用
@MyTest
public class AnnotationTest {
// @MyTest
// private String name;
@MyTest
@MyDemo(value = "Annotation",name="張三",str={"java","C++"})
public static void test() {
System.out.println("Hello World");
}
public static void main(String[] args) {
test();
}
}
如果把@MyTest修飾在成員變量上就會(huì)報(bào)錯(cuò)—>java: 注釋類型不適用于該類型的聲明
注解的解析
注解的操作中經(jīng)常需要解析,注解的解析就是判斷是否存下注解,存在注解就解析出內(nèi)容。
與注解解析相關(guān)的接口
- Annotation: 注解的頂級(jí)接口,注解都是Annotation類型的對(duì)象
- AnnotatedElement:該接口定義了與注解解析相關(guān)的解析方法
相關(guān)API如下
方法 | 說明 |
---|---|
Annotation[] getDeclaredAnnotations() | 獲得當(dāng)前對(duì)象上使用的所有注解,返回注解數(shù)組。 |
T getDeclaredAnnotation(Class annotationClass) | 根據(jù)注解類型獲得對(duì)應(yīng)注解對(duì)象 |
boolean isAnnotationPresent(Class annotationClass) | 判斷當(dāng)前對(duì)象是否使用了指定的注解,如果使用了則返回true,否則false |
所有的類成分Class, Method , Field , Constructor,都實(shí)現(xiàn)了AnnotatedElement接口他們都擁有解析注解的能力。
注解解析案例
首先定義一個(gè)MyTest2注解
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTest2 {
String value();
String name();
boolean flag() default true;
String [] str();
}
在Demo類和方法上使用
@MyTest2(value = "大小姐",name ="林黛玉",str={"java","C++"})
public class Demo {
@MyTest2(value = "小小姐",name ="薛寶釵",str={"java","Python"})
public void test() {
}
}
解析類上的注解
public class AnnotationTest2 {
public static void main(String[] args) {
//1.得到class對(duì)象
Class<Demo> demoClass = Demo.class;
//2.判斷類上是否包含注解
if (demoClass.isAnnotationPresent(MyTest2.class)) {
MyTest2 myTest2 = demoClass.getDeclaredAnnotation(MyTest2.class);
System.out.println(myTest2.value());
System.out.println(myTest2.name());
System.out.println(myTest2.flag());
System.out.println(Arrays.toString(myTest2.str()));
}
}
}
運(yùn)行結(jié)果:
解析方法上的注解
public class AnnotationTest3 {
public static void main(String[] args) throws NoSuchMethodException {
//1.得到class對(duì)象
Class<Demo> demoClass = Demo.class;
Method test = demoClass.getDeclaredMethod("test");
//2.判斷方法對(duì)象上是否包含注解
if (test.isAnnotationPresent(MyTest2.class)) {
MyTest2 myTest2 = test.getDeclaredAnnotation(MyTest2.class);
System.out.println(myTest2.value());
System.out.println(myTest2.name());
System.out.println(myTest2.flag());
System.out.println(Arrays.toString(myTest2.str()));
}
}
}
運(yùn)行結(jié)果:
模擬Junit中的@Test
我們定義若干個(gè)方法,只要加了MyTest注解,就可以在啟動(dòng)時(shí)被觸發(fā)執(zhí)行
分析
- 定義一個(gè)自定義注解MyTest,只能注解方法,存活范圍是一直都在。
- 定義若干個(gè)方法。只要有@MyTest注解的方法就能在啟動(dòng)時(shí)被觸發(fā)執(zhí)行,沒有這個(gè)注解的方法不能執(zhí)行。
示例代碼
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class TestDemo {
@MyTest
public void test1() {
System.out.println("test1");
}
@MyTest
public void test2() {
System.out.println("test2");
}
@MyTest
public void test3() {
System.out.println("test3");
}
@MyTest
public void test4() {
System.out.println("test4");
}
public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
TestDemo t = new TestDemo();
//啟動(dòng)程序
//1.得到TestDemo對(duì)象
Class<TestDemo> testDemoClass = TestDemo.class;
//提取類中的方法
Method[] declaredMethods = testDemoClass.getDeclaredMethods();
//觸發(fā)方法
for (Method method : declaredMethods) {
if (method.isAnnotationPresent(MyTest.class)) {
method.invoke(t);
}
}
}
}
運(yùn)行結(jié)果:
各位看官如果覺得文章寫得不錯(cuò),點(diǎn)贊評(píng)論關(guān)注走一波!謝謝啦!。文章來源:http://www.zghlxwxcb.cn/news/detail-650459.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-650459.html
到了這里,關(guān)于《Java-SE-第三十八章》之注解的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!