Java反射機(jī)制經(jīng)常與注解搭配荚坞,出現(xiàn)在各大框架中盖灸,是框架的靈魂所在盟榴,貫穿了整個(gè)框架的構(gòu)成酬诀。在此對(duì)這兩個(gè)Java特性做一個(gè)總結(jié)脏嚷。
反射
能夠分析類能力的程序成為反射(reflective)---from Java核心技術(shù)卷Ⅰ
通過Java的反射機(jī)制,可以在程序中訪問已經(jīng)加載到JVM中的Java對(duì)象的描述料滥,實(shí)現(xiàn)訪問然眼、檢測(cè)艾船、修復(fù)和修改描述Java本身對(duì)象的功能葵腹,Java中的java.lang.reflect包提供使用注解功能高每。
那么,++如何才能分析類能力呢践宴?++首先需要得到類對(duì)象鲸匿,獲取類對(duì)象有三種方法,分別是:
1. Class cl = Class.forName("全類名");
2. Class cl = 類名.class;
3. Class cl = 對(duì)象.getClass();
快速使用阻肩,獲取MyObject類的所有方法并打哟丁:
Method[] methods = MyObject.class.getMethods();
for(Method method : methods){
System.out.println("method = " + method.getName());
}
通過獲取到的類對(duì)象,就能輕松的得到類的成員變量烤惊、構(gòu)造方法乔煞、成員方法、類名柒室、注解等等渡贾。具體獲取方法有很多,不在此一一例舉了雄右。
注解
注解(也被稱為元數(shù)據(jù))為我們?cè)诖a中添加信息提供了一種形式化的方法空骚,使我們可以在稍后某個(gè)時(shí)刻非常方便地使用這些數(shù)據(jù)。 ---from Java編程思想
注解是眾多引入到JavaSE5中的重要的語言變化之一擂仍。它們可以提供用來完整地描述程序所需地信息囤屹,而這些信息是無法用Java來表達(dá)的。注解使得我們能夠以將由編譯器來測(cè)試和驗(yàn)證的格式逢渔,存儲(chǔ)有關(guān)程序的額外信息肋坚。注解可以用來生成描述符文件,甚至或是新的類的定義复局。
注解形式:
public @interface Action { // 無屬性值
}
public @interface Action { // 有屬性值
String action() default "A";
int value() default 0;
}
元注解:用于描述注解的注解
-
@Target:描述注解能用作用的位置
- ANNOTATION_TYPE:表示用于Annotation的類型
- TYPE:作用與類冲簿、接口、枚舉
- CONSTRUCTOR:作用于構(gòu)造方法
- FIELD:作用于屬性
- METHOD:作用于方法
- PARAMETER:作用于參數(shù)
- LOCAL_VARIABLE:表示局部變量
- PACKAGE:表示用于包
-
@Retention:設(shè)置注解的有效范圍
- SOURCE:不編譯到Annotation類的文件中
- CLASS:編譯到Annotation的文件中亿昏,運(yùn)行時(shí)不加在到JVM中
- RUNTING:運(yùn)行時(shí)加載到JVM中峦剔,有效范圍最大
Decomented: 注解會(huì)在API文檔中體現(xiàn)
Inherited: 描述注解是否被子類繼承
注解與反射:實(shí)例
聲明兩個(gè)注解:
@Target(ElementType.CONSTRUCTOR)
@Retention(RetentionPolicy.RUNTIME)
public @interface Action {
String action() default "構(gòu)造函數(shù)";
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldAnnotation {
String describe() default "描述";
Class type() default void.class;
注解@Action 使用于構(gòu)造函數(shù),有一個(gè)描述屬性角钩,@FieldAnnotation適用于注解屬性常量吝沫,包含一個(gè)String類型的描述和修飾的類型
使用注解:
public class ConstructorExample {
@FieldAnnotation(describe = "名字" ,type = String.class)
public String name;
@FieldAnnotation(describe = "分?jǐn)?shù)",type = int.class)
protected int core;
@Action()
public ConstructorExample(String name, int core) throws NumberFormatException {
this.core = core;
this.name = name;
}
}
反射獲取:
public class ReflectConstructor {
public static void main(String[] args) {
ConstructorExample constructorExample = new ConstructorExample("ABC",10);
Class<? extends ConstructorExample> classExample = constructorExample.getClass();
Constructor[] constructors = classExample.getDeclaredConstructors();
for (int i = 0; i < constructors.length; i++) {
Constructor constructor = constructors[i];
if (constructor.isAnnotationPresent(Action.class)){//是否包含Action.class注解
System.out.println("包含Action注解");
Action action = (Action) constructor.getAnnotation(Action.class);
System.out.println("注解值為 :"+action.action());
}
System.out.println("-------------");
}
Field[] fields = classExample.getDeclaredFields();
for (Field f: fields) {
System.out.println("屬性名稱 = "+f.getName());
System.out.println("屬性類型 = "+f.getType());
try {
if (f.isAnnotationPresent(FieldAnnotation.class)) {
System.out.println("使用FieldAnnotation注解");
FieldAnnotation annotation = f.getAnnotation(FieldAnnotation.class);
System.out.println("FieldAnnotation注解參數(shù):");
System.out.println("Describe:"+annotation.describe());
System.out.println("Type:"+annotation.type());
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("-------------");
}
}
}