Java注解和反射——入門篇

注解

?一般情況下,注解是用來(lái)給程序員、編譯器提示的,就比如 @NoNull 就是用來(lái)提示不為空,在null時(shí),編譯器會(huì)根據(jù)注解報(bào)出相關(guān)的異常。

?但是注釋還有一個(gè)很重要的作用就是和反射一起使用,我們可以通過(guò)反射拿到被注釋的字段、方法、類,當(dāng)然也可以拿到注釋中的信息。

?還是先說(shuō)用來(lái)注解注解的注解(原生注解),哈哈哈!

@Target

?表示該注解可以用于什么地方,可能的ElementType參數(shù)有:

  • CONSTRUCTOR:構(gòu)造器的聲明
  • FIELD:域聲明(包括enum實(shí)例)
  • LOCAL_VARIABLE:局部變量聲明
  • METHOD:方法聲明
  • PACKAGE:包聲明
  • PARAMETER:參數(shù)聲明
  • TYPE:類、接口(包括注解類型)或enum聲明


@Retention

?表示需要在什么級(jí)別保存該注解信息??蛇x的RetentionPolicy參數(shù)包括:

  • SOURCE:注解將被編譯器丟棄
  • CLASS:注解在class文件中可用,但會(huì)被VM丟棄
  • RUNTIME:VM將在運(yùn)行期間保留注解,因此可以通過(guò)反射機(jī)制讀取注解的信息。


@Document

?將注解包含在Javadoc中。

@Inherited

?允許子類繼承父類中的注解。

?看完了若是一臉懵,請(qǐng)看注解的構(gòu)造方式:

//這里就實(shí)現(xiàn)了MyAnnotationTest這個(gè)注解的構(gòu)建
//這里代表該注解是用來(lái)注解方法、并且可以被反射獲取信息

@Target(ElementType.METHOD)    
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotationTest {
   String name() default " ";
   int id()default 0;
 } 

?注解的使用:

//該注解的使用:
//賦值
@MyAnnotationTest(name = "小明" ,id = 1)
public void annnotationMethod(){
    System.out.println("這是一個(gè)被注解的方法");
}

?是不是感覺(jué)這里看不出來(lái)什么特殊含義。但是,假如說(shuō),對(duì)我自己,這個(gè)注解代表被注解的方法是用來(lái)干某些耗時(shí)操作的,那么是不是就有意義了?

?當(dāng)然這樣使用還是太淺層了,我們來(lái)結(jié)合反射試試!

反射

?我們還是先不談注解和反射搭配好伐?先單獨(dú)談?wù)劮瓷洌?strong>JAVA反射機(jī)制是在運(yùn)行狀態(tài)中,對(duì)于任意一個(gè)類,都能夠知道這個(gè)類的所有屬性和方法;對(duì)于任意一個(gè)對(duì)象,都能夠調(diào)用它的任意一個(gè)方法和屬性;這種動(dòng)態(tài)獲取的信息以及動(dòng)態(tài)調(diào)用對(duì)象的方法的功能稱為Java語(yǔ)言的反射機(jī)制。

?首先定義了一個(gè)Student類,這個(gè)類是我們想象出來(lái)的(可以啥子都有),專門用來(lái)接下來(lái)實(shí)現(xiàn)反射用的。一般情況下,我們是在對(duì)這個(gè)類一點(diǎn)都不了解的情況下才會(huì)想著去獲取它的信息,好奇心按捺不住了啊?。?!

?在另外的類里面獲取Student的信息是這樣實(shí)現(xiàn)的:

//先獲取類的對(duì)象
private static Class<?> c;

static {
    try {
        c = Class.forName("com.example.hp.javaclasstest.reflection.Student");
        //另外一種方法是傳遞當(dāng)前類的對(duì)象過(guò)去,使用object.getClass()獲取到類對(duì)象。
    } catch (ClassNotFoundException e) {
        c = null;
    }
}

//這里就是獲取到所有的構(gòu)造函數(shù),是可以直接將它打印出來(lái)的
Constructor<?>[] constraints = c.getConstructors();

//這里是獲取到某一個(gè)方法
try {
    Method method = c.getMethod("showMyData",null);
    //這個(gè)null是指該方法的返回對(duì)象,如果是String類型,則是String.class
} catch (NoSuchMethodException e) {
    e.printStackTrace();
}

?其它的字段、方法、類的獲取方式待自己慢慢探索吧。

?但是萬(wàn)一有的小伙伴手癢,又想使用它拿到的方法該怎么辦呢?

?沒(méi)關(guān)系,上熱騰騰的代碼:

//獲取到這個(gè)類的單例
Object object = null;
try {
    object = c.getConstructor().newInstance();
} catch (Exception e) {
    e.printStackTrace();
}

//實(shí)現(xiàn)某個(gè)方法的使用
//object:單例,null:該方法傳入?yún)?shù),無(wú)則null
method.invoke(object,null);

是不是感受出來(lái)什么了?通過(guò)反射獲取一個(gè)類的信息就是這么簡(jiǎn)單!

其實(shí)在字段或者方法上面加上注解也就是比普通的特殊了那么一丟丟,我們稍加判斷同樣是能夠獲取到被注解了的對(duì)象。

筆者手懶,就通通使用上面已經(jīng)建好了的對(duì)象。

上代碼?。?!

//獲取到Student的所有公開(kāi)方法
Method[] methods = c.getMethods();

//注意,請(qǐng)仔細(xì)看這里?。?!
for(Method m:methods){
    //判斷方法是否被MyAnnotationTest這個(gè)注解類注解
    if(m.isAnnotationPresent(MyAnnotationTest.class)){  
        //這個(gè)m就是被 MyAnnotationTest 注釋了的方法
        //我們直接將它拿出來(lái)吧,return出來(lái)。
        return m;
    }
}

先緩口氣,我們邁出了很大一步,我們已經(jīng)獲取到了被注釋了的方法。接下來(lái)就是按照我們自己的需求來(lái)寫了。

假如,我只是要實(shí)現(xiàn)這個(gè)方法,那么就可以采用invoke()方法去實(shí)現(xiàn)啦。但是我要想知道注釋里面的信息呢(例如上面的"小明",1)。

這也是超級(jí)簡(jiǎn)單的:

//獲取到注釋類對(duì)象
MyAnnotationTest annotation = m.getAnnotation(MyAnnotationTest.class);

//獲取到我的"小明 "
String name = annotation.name;

輕而易舉實(shí)現(xiàn)啦。

總結(jié)

Java的注解和反射搭配使用是有很大作用的,這兩者搭配是可以實(shí)現(xiàn)超大程度的解耦。我在這個(gè)類里面實(shí)現(xiàn)了注解,我可以在另外一個(gè)毫不相關(guān)的類里面去獲得這個(gè)類的內(nèi)容,并且實(shí)現(xiàn)里面的方法。

很多好的三方庫(kù)的都是實(shí)現(xiàn)的注解和反射,例如Dagger2、Retrofit、ButterKnife...但是這些第三庫(kù)不是這么簡(jiǎn)單去實(shí)現(xiàn)的,它們會(huì)生成工具類來(lái)快速實(shí)現(xiàn)信息獲取。

但是在Java中實(shí)現(xiàn)反射可是一件“費(fèi)勁”的事兒,是比較消耗CPU資源的。所以,請(qǐng)勿濫用反射!

由于筆者水平有限,文中若有錯(cuò)誤,請(qǐng)大膽指出,謝謝!
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容