Java 基礎-反射與註解
阿新 • • 發佈:2019-01-02
一、Class
1. Class 型別的獲取
- Clazz.class;
- clazz.getClass();
- Class.forName(String className);
2. 根據 Class 型別建立類例項
Class clazzType = Clazz.class;
try{
// Clazz 必需含有無參構造方法
Clazz clazzBean = (Clazz)clazzType.newInstance();
}catch(Exception e){
e.printStackTrace();
}
3. Class 載入
載入方式 | 實現 | 描述 |
---|---|---|
靜態載入 | new Clazz() | 在編譯過程就載入 |
動態載入 | (Class.forName(String className)).newInstance() | 執行時才載入 |
二、反射
1. 反射的基本應用
class Clazz{
public void print(String str){
System.out.print("str");
}
}
// 1. 獲取類資訊
Clazz clazz = new Clazz();
Class c = clazz.getClass();
try {
// 2. 獲取類方法
Method m = c.getMethod("print", String.class);
// 3. 實現方法的反射操作
m.invoke(clazz, "設定輸出內容");
}catch(Exception e){
e.printStackTrace();
}
2. 反射在泛型中的應用
反射操作位於編譯之後,即編譯後為泛型物件將失去泛型特徵
ArrayList<String> list = new ArrayList<String>();
Class c = list.getClass();
try {
// 通過反射繞過編譯時對插入值型別的判斷
Method m = c.getMethod("add", Object.class);
m.invoke(list, 1);
}catch(Exception e){
e.printStackTrace();
}
三、註解
1. 概念理解
- 成員型別必需是原始型別 及 String,Class, Annotation, Enumeration
- 如果註解成員只有一個,則成員命名必需為 value(),在使用時可忽略成員名與賦值號(=)
- 註解類可無成員物件,稱之為標識註解
// 元註解
@Target({ElementType.METHOD,ElementType.TYPE}) // 作用域
@Retention(RetentionPolicy.RUNTIME) // 宣告生命週期
@Inherited // 允許子類繼承,且僅繼承類註解
@Documented // 生成 javadoc 時包含註解資訊
// 使用@interface 定義註解
public @interface Description{
// 無參無異常的成員宣告
String sex();
String author();
// 成員的預設值宣告
int age() default 18;
}
作用域 | 描述 |
---|---|
@Target(ElementType.TYPE) | 介面、類、列舉、註解 |
@Target(ElementType.FIELD) | 欄位、列舉的常量 |
@Target(ElementType.METHOD) | 方法 |
@Target(ElementType.PARAMETER) | 方法引數 |
@Target(ElementType.CONSTRUCTOR) | 建構函式 |
@Target(ElementType.LOCAL_VARIABLE) | 區域性變數 |
@Target(ElementType.ANNOTATION_TYPE) | 註解 |
@Target(ElementType.PACKAGE) | 包 |
生命週期/註解分類 | 描述 |
---|---|
@Retention(RetentionPolicy.SOURCE) | 原始碼註解(僅原始碼中存在,編譯後不存在) |
@Retention(RetentionPolicy.CLASS) | 編譯時註解(原始碼與編譯後均存在) |
@Retention(RetentionPolicy.RUNTIME) | 執行時註解(執行時存在,影響邏輯處理) |
2. 自定義
語法: @<註解名>(<成員名1>=<成員值>,<成員名2>=<成員值2>,…)
@Description(sex="I am boy", author="gzejia",age="25")
public class Clazz{
@Description(sex="I am boy", author="gzejia",age="25")
public String manSex(){
return "boy";
}
}
3. 註解解析
通過反射獲取類、函式或成員上的執行時註解資訊,從而實現動態控制程式執行的邏輯
try{
// 1.使用類載入器載入類
Class c = Class.forName("...Clazz");
// 2.判斷是否存在註解資訊
boolean isExist = c.isAnnotationPresent(Description.class);
// 3.獲取類註解資訊
if(isExist){
Description d = (Description)c.getAnnotation(Description.class);
System.out.println(d.sex());
}
// 4.獲取方法註解資訊
Method[] ms = c.getMethods();
for(Method m : ms){
boolean isMExist = m.isAnnotationPresent(Description.class);
if(isExist){
Description d = (Description)m.getAnnotation(Description.class);
System.out.println(d.author());
}
}
// 獲取註解資訊方式二(以獲取方法註解資訊為例)
for(Method m : ms){
Annotation[] as = m.getAnnotations();
for(Annotation a : as){
if(a instanceof Description){
Description d = (Description)a;
System.out.println(String.valueOf(d.age()));
}
}
}
}catch(Exception e){
e.printStackTrace();
}