//Java中的反射
//Java反射機制是指在運行狀態中
//
//對於任意一個類,都能知道這個類的所有屬性和方法;
//對於任何一個對象,都能夠調用它的任何一個方法和屬性;
//這樣動態獲取新的以及動態調用對象方法的功能就叫做反射。
//反射機制的相關類
//
//Class 代表類實類
//Field 代表類的成員變量
//Method 代表類方法
//Constructor 代表類的構造函數
Class clz = ContentBean.class;
try {//獲得公有屬性
Field field = clz.getField("content");
System.out.println("field = " + field.getName());
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
//獲得所有公有屬性
Field[] fields = clz.getFields();
for (Field f :
fields) {
System.out.println("field = " + f.getName());
}
System.out.println("_____________________________________________________________");
try {//獲得某個類的屬性
Field declaredField = clz.getDeclaredField("author");
System.out.println("修飾符:" + Modifier.toString(declaredField.getModifiers())
+ " declaredField = " + declaredField.getName());
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
//獲得所有屬性
Field[] declaredFields = clz.getDeclaredFields();
for (Field df :
declaredFields) {
System.out.println("修飾符:" + Modifier.toString(df.getModifiers())
+ " declaredField = " + df.getName());
}
System.out.println("_____________________________________________________________");
//獲得與參數匹配的公有註解對象
Annotation annotation = clz.getAnnotation(Deprecated.class);
if (annotation != null)
System.out.println("annotation:" + annotation.annotationType().getName());
//獲得所有公有註解對象
Annotation[] annotations = clz.getAnnotations();
for (Annotation a :
annotations) {
System.out.println("修飾符:" + Modifier.toString(a.annotationType().getModifiers()) + " a = " + annotation.annotationType().getName());
}
System.out.println("_____________________________________________________________");
//獲得某個匹配的註解對象
Annotation declaredAnnotation = clz.getDeclaredAnnotation(Deprecated.class);
if (declaredAnnotation != null)
System.out.println("declaredAnnotation:" + declaredAnnotation.annotationType().getName());
//獲得所有註解對象
Annotation[] declaredAnnotations = clz.getDeclaredAnnotations();
for (Annotation da:
declaredAnnotations) {
System.out.println("修飾符:" + Modifier.toString(da.annotationType().getModifiers()) + " da:" + da.annotationType().getName());
}
System.out.println("_____________________________________________________________");
//獲得某個參數類型匹配的公有構造函數
try {
Constructor constructor = ContentBean.class.getConstructor();
System.out.println("constructor = " + constructor.getName());
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
//獲得所有公有構造函數
Constructor[] constructors = ContentBean.class.getConstructors();
for (Constructor c :
constructors) {
System.out.println("修飾符:" + Modifier.toString(c.getModifiers()) + " c:" + c.getName());
}
System.out.println("_____________________________________________________________");
//獲得某個參數類型匹配的構造函數
try {
Constructor dc = ContentBean.class.getDeclaredConstructor();
System.out.println("dc = " + dc.getName());
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
//獲得所有構造函數
Constructor[] dcs = ContentBean.class.getDeclaredConstructors();
for (Constructor dc: dcs) {
System.out.println("修飾符:" + Modifier.toString(dc.getModifiers()));
System.out.println("所有參數:");
Parameter[] parameters = dc.getParameters();
for (Parameter p :
parameters) {
System.out.println("修飾符 = " + p.getType().getSimpleName() + " p = " + p.getName());
}
}
System.out.println("_____________________________________________________________");
//獲得某個參數類型與函數名稱匹配的函數
try {
Method method = ContentBean.class.getMethod("getName");
System.out.println("method = " + method.getName() + " " + method.getReturnType().getSimpleName());
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
//...........省略getMethods()、getDeclaredMethod(...)、getDeclaredMethods()...........
System.out.println(clz.isAnnotation());//是否是註解類型
System.out.println(clz.isAnnotationPresent(Deprecated.class));//是否被指定註解類型修飾
System.out.println(clz.isAnonymousClass());//是否是匿名類
System.out.println(clz.isArray());//是否是數組
System.out.println(clz.isEnum());//是否是枚舉類
System.out.println(clz.isInterface());//是否是接口類
System.out.println(clz.isLocalClass());//是否是局部類
System.out.println(clz.isMemberClass());//是否是內部類
//Field類
//equals(object):屬性與obj相等則返回true
//get(object):獲得obj中對應的屬性值
//set(object, value);設置obj中對應屬性值
ContentBean c = new ContentBean();
c.setAuthor("測試");
try {
Field field = clz.getDeclaredField("author");
field.setAccessible(true);
System.out.println("author = " + field.get(c));
field.set(c, "內容變了");
System.out.println("author = " + field.get(c));
} catch (IllegalAccessException | NoSuchFieldException e) {
e.printStackTrace();
}
//Method類
//invoke(obj, args...)
try {
Method method = clz.getDeclaredMethod("setAuthor", String.class);
method.invoke(c, "內容又變了");
Method method2 = clz.getDeclaredMethod("getAuthor");
System.out.println(method2.invoke(c));
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
//Constructor類
//newInstance方法
try {
Constructor constructor = clz.getDeclaredConstructor(String.class, String.class);
constructor.setAccessible(true);
ContentBean cb = (ContentBean)constructor.newInstance("dragon", "龍博");
System.out.println(cb.getName());
System.out.println(cb.getAuthor());
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
//正確構造反射的步驟
try {
Class<?> className = Class.forName("com.dragon.devl.test.ContentBean");
//獲取到類對象後,自行決定反射其內部哪些方法,比如反射setName方法
Method method = className.getDeclaredMethod("setName", String.class);
//獲取到方法對象後,需要構建對應的類實例,纔可以反射該方法
Constructor constructor = className.getDeclaredConstructor();
//constructor.setAccessible(true);無參構造函數是public類型,所以不需要設置權限
Object obj = constructor.newInstance();//調用該構造方法獲取對象
method.invoke(obj, "測試");//調用setName方法。
//最後我們輸出數據
Method getMethod = className.getDeclaredMethod("getName");
System.out.println(getMethod.invoke(obj));
//如果只是調用靜態方法,則不需要構造實例,直接使用method.invoke(null, args)調用
Method staticMethod = className.getDeclaredMethod("setDesc", String.class);
staticMethod.invoke(null, "設置靜態屬性值");
Method getStaticMethod = className.getDeclaredMethod("getDesc");
System.out.println(getStaticMethod.invoke(null));
System.out.println(ContentBean.getDesc());
} catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {///由於可能會出現找不到類的情況,所以需要捕獲異常
e.printStackTrace();
}
Java註解
Annotation(註解)就是Java提供了一種源程序中的元素關聯任何信息或者任何元數據(metadata)的途徑和方法。
Annotation是被動的元數據,永遠不會有主動行爲
//自定義註解,使用@interface表示這是一個註解,Annotation只有成員變量,沒有方法
//Annotation的成員變量在Annotation中以無形參的方法形式來聲明,其方法名定義了該成員變量的名字,其返回值定義了該成員變量的類型
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
@Documented
@Inherited
public @interface BindContent {
String content() default "nothing";
boolean canBeNull() default false;
}
//在自定義註解內部使用的註解稱之爲元註解
//@Retention 用來標記自定義註解的有效範圍
//1、RetentionPolicy.SOURCE:只在源代碼中保留,一般是用來增加代碼的理解性或者幫助代碼檢查之類的,例如override
//2、RetentionPolicy.CLASS:默認值,把註解保留到編譯後的字節碼文件中,但運行時無法得到
//3、RetentionPolicy.RUNTIME:保留到編譯後的字節碼文件中,同時也能在運行時獲取。
//@Target:指定Annotation用於修飾哪些程序元素
//內部包含一個value[]成員變量
//允許傳入以下值
//ElementType.TYPE:能修飾類、接口或枚舉類
//ElementType.FIELD:修飾成員變量
//ElementType.METHOD:修飾方法
//ElementType.PARAMETER:修飾參數
//ElementType.CONSTRUCTOR:修飾構造器
//ElementType.LOCAL_VARIABLE:修飾局部變量
//ElementType.ANNOTATION_TYPE:修飾註解
//ElementType.PACKAGE:修飾包
//@Documented表示可以在javadoc中被找到
//@Interited:表示註解裏的內容可以被子類繼承,只針對class類
//類繼承關係中,子類會繼承父類使用的註解中被@Inherited修飾的註解
//
//接口繼承關係中@Inherited的作用
//
//接口繼承關係中,子接口不會繼承父接口中的任何註解,不管父接口中使用的註解有沒有被@Inherited修飾
//
//類實現接口關係中@Inherited的作用
//
//類實現接口時不會繼承任何接口中定義的註解
然後通過反射來獲取對應的註解內容
@BindContent(content = "Class desc")
public class AnnotationTesting {
@BindContent()
public String content;
public void printInfo() {
System.out.println(content);
}
public static void main(String[] args) {
try {
Class c = Class.forName("com.dragon.devl.test.AnnotationTesting");
AnnotationTesting annotationTesting = (AnnotationTesting)c.newInstance();
Field[] fields = c.getDeclaredFields();
for (Field f :
fields) {
if (f.isAnnotationPresent(BindContent.class)) {
BindContent bc = f.getAnnotation(BindContent.class);
f.set(annotationTesting, bc.content());
}
}
annotationTesting.printInfo();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
}