前言
本篇文章講述java中注解的概念和注解的基礎(chǔ)用法,文章中舉例用到的注解、元注解只是一部分,平時工作中用到過,有錯誤或新的見解,請指出。
注解概念
注解你可以理解為是某個類、某個方法的標簽,有了這個標簽(注解),就具備了某一個功能,舉個例子,我們有一個類實現(xiàn)一個接口中的方法,在繼承的方法上面都會有@Override的注解,就代表了這個方法是屬于繼承方法;或者在方法使用@Deprecated注解,就表示該方法已經(jīng)過期,調(diào)用的時候方法上會有中劃線的提示。以上例子只是標識注解,還有更多的帶有成員或者自定義的注解,往下慢慢看來了解吧。
注解的分類
- jdk中的注解
例:@Override、@Deprecated等
- 來自第三方的注解
例:Retrofit中的@GET、@POST,Spring中的@Autowired等
- 自定義注解
根據(jù)原則定義自己需求的注解
上面說的三種注解的分類,jdk中的注解,需要我們?nèi)ゲ榭碼pi文檔,逐個了解,這里不多做贅述,第三方的注解,也是屬于自定義注解,是一些優(yōu)秀的框架中定義的注解,我們在平時的工作中會經(jīng)常用到,舉例的Retrofit是Android中應用非常廣泛的網(wǎng)絡(luò)框架;而spring則是java后臺常用的。最后一個自定義注解,就是我們今天主要要了解和學習的,看看怎樣去定義一個注解。
自定義注解原則
使用@interface關(guān)鍵字定義注解
成員以無參無異常的方式聲明
可以用default為成員設(shè)置默認值
添加元注解(下面會做單獨的介紹)
示例:
/**
* 元注解
*/
@Target(TYPE)
@Retention(RUNTIME)
@Inherited
@Documented
//@interface關(guān)鍵字
public @interface Description {
String name();//無參數(shù)無異常的方法聲明
String gender();
int age()default 18;//使用default字段設(shè)置默認值
}
注解中成員變量的規(guī)則要求
在注解中聲明的成員變量是有類型限制的,合法的類型包括基本數(shù)據(jù)類型及String、Class、Annotation、Enumeration,一般我們常用到就是基本數(shù)據(jù)類型和String
如果注解中只有一個成員,則方法名必須要寫成
value(),在使用的時候就可以忽略掉方法名和賦值符號(就是=)
示例:定義
@Target(TYPE)
@Retention(RUNTIME)
@Inherited
@Documented
public @interface Description2 {
//一個成員的定義 方法名為vaule
String value();
}
- 在注解中可以沒有成員,沒有成員的注解稱為標識注解,就類似于jdk中的
@Override、@Deprecated
元注解:注解的注解
我們看到在定義自定義注解的時候,上面定義了一些@Target、@Inherited等字段,它們有什么作用呢?看看下面的解釋
@Target注解
Target注解可以規(guī)定在哪些地方使用
Target定義的成員類型是ElementType數(shù)組,Target中可以傳入多個參數(shù)
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.ANNOTATION_TYPE})
public @interface Target {
ElementType[] value();
}
- 參數(shù)的類型
//使用的jdk8中的ElementType 在8之前沒有TYPE_PARAMETER和TYPE_USE兩個參數(shù)值
ANNOTATION_TYPE,//注釋類聲明
CONSTRUCTOR,//構(gòu)造方法聲明
FIELD,//字段聲明
LOCAL_VARIABLE,//局部變量聲
METHOD,//方法聲明
PACKAGE,//包聲明
PARAMETER,//參數(shù)聲明
TYPE,//類、接口聲明
TYPE_PARAMETER,//類型參數(shù)聲明
TYPE_USE;//沒搞懂這個,官方API中給出的注釋是Use of a type
- 示例:
@Target({METHOD,TYPE})表示可以作用于方法、類、接口等
@Retention注解
Retention指的是該注解的生命周期
參數(shù)類型
CLASS,//只在源碼顯示,編譯時會丟失
RUNTIME,//編譯時會記錄到class中,運行時忽略
SOURCE;//運行時存在,可以通過反射獲取
@Inherited注解
Inherited表示允許子類繼承
屬于標識注解
@Documented注解
生成javadoc時會包含注解的信息
屬于標識注解
自定義注解用法:
//多個成員用法
@Description(name = "gdy",gender = "man",age = 20)
public String getName() {
return name;
}
//只有一個成員定義
@Description2("gdy")
public String getAge() {
return age;
}
下面我們就用一個簡單的小demo來演示一下注解的具體使用
代碼實例
定義只有一個成員的注解
@Documented
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface TestAnn {
String value();
}
使用注解
//定義了一個接口
public interface Person {
String name();
String gender();
int age();
}
//實現(xiàn)類中使用注解
@TestAnn("我是一個person實現(xiàn)類")
public class DuoDuo implements Person {
@Override
@TestAnn("我的名字叫多多")
public String name() {
return null;
}
@Override
public String gender() {
return null;
}
@Override
public int age() {
return 0;
}
}
在運行時解析注解
public class myClass {
public static void main(String[] args){
try {
//1、使用類加載器加載類
Class duo = Class.forName("com.rxjava.model.DuoDuo");
//2、找到類上面的注解
boolean isExist = duo.isAnnotationPresent(TestAnn.class);
if (isExist) {
//3、獲取注解實例,并輸出值
TestAnn t = (TestAnn) duo.getAnnotation(TestAnn.class);
System.out.println(t.value());
}
//4、獲取每個方法上的值
Method[] duoMethods = duo.getMethods();
for (Method duoM : duoMethods) {
boolean isMExist = duoM.isAnnotationPresent(TestAnn.class);
if (isMExist) {
TestAnn tm = duoM.getAnnotation(TestAnn.class);
System.out.println(tm.value());
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
輸出結(jié)果

參考
本篇文章是根據(jù)慕課網(wǎng)java注解完全解析,總結(jié)出來的筆記,想更細致的了解注解的使用,可移步到慕課網(wǎng)去觀看視頻,另外還有一篇大神講解的深入簡出、通俗易懂,也可一并觀摩。