總結
1.註解只是相當於一種標識,標誌着被修飾的類,方法,屬性等應該具有的公共的功能。這一點可以從註解的源碼看 出來,註解的源碼只有屬性變量,並沒有方法;這些屬性變量的不同取值映射爲不同的功能
2.通過反射解析出註解的屬性值,並根據屬性值是否爲指定的值,來判斷是否執行相關代碼
1:Java中常見註解
詳細介紹:基本內置註解
- @Override
用在方法上,表示這個方法重寫了父類的方法,如toString()。 - @Deprecated
表示這個方法已經過期,不建議開發者使用。(暗示在將來某個不確定的版本,就有可能會取消掉) - @SafeVarargs
參數安全類型註解。它的目的是提醒開發者不要用參數做一些不安全的操作,它的存在會阻止編譯器產生 unchecked 這樣的警告 - @FunctionalInterface
用於約定函數式接口。 如果接口中只有一個抽象方法(可以包含多個默認方法或多個static方法),該接口稱爲函數式接口。函數式接口其存在的意義,主要是配合Lambda 表達式 來使用。
2: 註解分類
按運行機制分:
- 源碼註解
註解只在源碼中存在,編譯成.class文件就不存在了 - **編譯時註解 **
註解在源碼和.class文件中都會存在。比如說@Override - **運行時註解 **
在運行階段還會起作用,甚至會影響運行邏輯的註解。比如說@Autowired
3:自定義註解
- **自定義註解的語法要求 **
package grammar;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Description 自定義註解的語法要求
* @since 2018年10月29日 下午4:47:07
* @author
*/
/***************** 元註解 **********************************/
/*@Target 表示這個註解能放在什麼位置上,是隻能放在類上?還是即可以放在方法上,又可以放在屬性上
*
* ElementType.TYPE:能修飾類、接口或枚舉類型
ElementType.FIELD:能修飾成員變量
ElementType.METHOD:能修飾方法
ElementType.PARAMETER:能修飾參數
ElementType.CONSTRUCTOR:能修飾構造器
ElementType.LOCAL_VARIABLE:能修飾局部變量
ElementType.ANNOTATION_TYPE:能修飾註解
ElementType.PACKAGE:能修飾包
* */
@Target({ElementType.METHOD , ElementType.TYPE})
/*@Retention
* 表示生命週期,
*
* RetentionPolicy.SOURCE: 註解只在源代碼中存在,編譯成class之後,就沒了。@Override 就是這種註解
*
* RetentionPolicy.CLASS: 註解在java文件編程成.class文件後,依然存在,但是運行起來後就沒了
* @Retention的默認值,即當沒有顯式指定@Retention的時候,就會是這種類型。
*
* RetentionPolicy.RUNTIME: 註解在運行起來之後依然存在,程序可以通過反射獲取這些信息
*
* */
@Retention( RetentionPolicy.RUNTIME)
/*@Inherited 表示該註解具有繼承性
如果一個超類被 @Inherited 註解過的註解進行註解的話,那麼如果它的子類沒有被任何註解應用的話,那麼這個子類就繼承了超類的註解。*/
@Inherited
//元註解肯定是和文檔有關。它的作用是能夠將註解中的元素包含到 Javadoc 中去
@Documented
//使用 @interface 關鍵字定義註解
public @interface Description {
/* 成員變量
* 1. 註解的定義中以“無形參的方法”形式來聲明,其方法名定義了該成員變量的名字,其返回值定義了該成員變量的類型
*
* 2. 註解中定義屬性時它的類型必須是 8 種基本數據類型外加 類、接口、註解及它們的數組
*
* 3. 如果註解只有一個成員,則成員名必須取名爲 value() ,在使用時可以忽略成員名和賦值號(=)
*
* 4. 註解類可以沒有成員,沒有成員的註解稱爲標識註解
* */
String desc();
String author();
//可以用 default 爲成員指定一個默認的值
int age() default 18;
}
- **使用自定義註解 **
@<註解名>(<成員名1>=<成員值1>,<成員名2>=<成員值2>,..)
package grammar;
@Description(desc="I am" ,author="liu",age=22)
public class UseAnnotation {
public String Test() {
return "red";
}
}
- **解析註解 **
概念: 通過反射獲取類、函數或成員上的運行時註解信息,從而實現動態控制程序運行的邏輯。注意,解析註解時, @Retention(RetentionPolicy.RUNTIME) 是必須的。
1. 先獲取類對象
2. 類對象調用 isAnnotationPresent(Class<? extends Annotation> annotationClass)判斷是否應用了某個註解
3. 通過 getAnnotation() 方法來獲取 Annotation 對象,或者getAnnotations() 方法獲取所有應用在該類上的註解
示例:
註解類:
package grammar;
@Target({ElementType.METHOD , ElementType.TYPE})
@Retention( RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface DesSimple {
String value();
}
應用註解類:
package grammar;
@DesSimple("this is a type ano")
public class Child {
@DesSimple("this is a method ano")
public String name() {
return "name";
}
}
解析註解類:
package grammar;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
public class ParseAnnotation {
public static void main(String[] args) {
try {
//1.使用類加載器加載類對象
Class clazz = Class.forName("grammar.Child");
//2. 判斷是否應用了這個註解
boolean hasAnno = clazz.isAnnotationPresent(DesSimple.class);
//3. 獲取Annotation對象
if(hasAnno) {
DesSimple ds = (DesSimple)clazz.getAnnotation(DesSimple.class);
System.out.println(ds.value());
}
//4. 找到方法上的註解
Method[] ms = clazz.getMethods();
/******** 第一種解析方式 ************/
for(Method m:ms) {
boolean isMExist = m.isAnnotationPresent(DesSimple.class);
if(isMExist ) {
DesSimple dsm = (DesSimple)m.getAnnotation(DesSimple.class);
System.out.println(dsm.value());
}
}
/************ 另一種解析方式 ******************/
for(Method m: ms) {
Annotation[] ans = m.getAnnotations();//獲取所有註解在該方法上的註解
for(Annotation an:ans) {
if(an instanceof DesSimple) {
DesSimple desSimple = (DesSimple)an;
System.out.println(desSimple.value());
}
}
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}