原文連接:小ben馬的java Reflection(反射)基礎知識講解java
1.1)使用 "Class#forName"git
public static Class<?> forName(String className) throws ClassNotFoundException;
若是沒有獲取到Class對象,則拋出異常 ClassNotFoundException
;github
eg:數組
Class<?> customerClazz = Class.forName("cn.xiaobenma.demo.core.reflection.VipCustomer");
1.2)使用某個類的 ".class",eg:code
Class<?> customerClazz = VipCustomer.class;
1.3)某個對象的 "#getClass()",eg:component
VipCustomer customer = new VipCustomer("001", "小ben馬", "10086", VipCustomer.VIP_ADVANCED); Class<?> customerClazz = customer.getClass();
咱們一般使用 "instanceof" 來判斷對象是否爲某個類的實例。一樣,能夠使用 "Class#isInstance()" 來判斷對象
public native boolean isInstance(Object obj);
例子:blog
boolean isCustomer = customer instanceof VipCustomer; isCustomer = VipCustomer.class.isInstance(customer);
若是person爲null, 上述例子都返回false。索引
3.1)使用 "Class#newInstance()": 要保證能訪問類的無參構造方法ip
public T newInstance() throws InstantiationException, IllegalAccessException;
3.2)經過 "Constructor#newInstance(Object ... initargs)"
public T newInstance(Object ... initargs) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException
eg:
Constructor<VipCustomer> constructor = getVipCustomerClass().getConstructor(String.class, String.class, String.class, int.class); VipCustomer customer = constructor.newInstance("001", "小ben馬", "10086", VipCustomer.VIP_ADVANCED);
在Class中定義的方法以下:
//a. 獲取當前類及其父類,全部`public`類方法和成員方法 public Method[] getMethods() throws SecurityException; //b. 經過方法名、參數類型,獲取單個`public`類方法或者成員方法(當前類或父類定義的) public Method getMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException; //c. 獲取當前類(不包括超類)定義的全部類方法和成員方法 public Method[] getDeclaredMethods() throws SecurityException; //d. 經過方法名、參數類型,獲取單個當前類(不包括超類)定義的類方法或成員方法 public Method getDeclaredMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException;
在Class中定義的方法以下:
//a. 獲取當前類全部`public`構造方法 public Constructor<?>[] getConstructors() throws SecurityException; //b. 根據參數類型,獲取當前類單個`public`構造方法 public Constructor<T> getConstructor(Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException; //c. 獲取當前類全部構造方法 public Constructor<?>[] getDeclaredConstructors() throws SecurityException; //d. 根據參數類型,獲取當前類單個構造方法 public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException;
在Class中定義的方法以下:
//a. 獲取當前類及其超類,全部`public`類變量和成員變量 public Field[] getFields() throws SecurityException; //b. 經過名稱,獲取當前類或超類,單個`public`類變量或者成員變量 public Field getField(String name) throws NoSuchFieldException, SecurityException; //c. 獲取當前類(不包括超類),全部類變量和成員變量 public Field[] getDeclaredFields() throws SecurityException; //d. 經過名稱,獲取當前類(不包括超類),單個類變量或成員變量 public Field getDeclaredField(String name) throws NoSuchFieldException, SecurityException;
eg:
Method setRank = getVipCustomerClass().getDeclaredMethod("setRank", int.class); setRank.invoke(customer, VipCustomer.VIP_NORMAL);
8.1) Field#set(Object obj, Object value): 經過對象和變量值,設置變量,eg:
Field field = getVipCustomerClass().getDeclaredField("rank"); field.set(customer, VipCustomer.VIP_ADVANCED);
8.2) Field#get(Object obj): 經過對象獲取變量值,eg:
Field field = getVipCustomerClass().getDeclaredField("rank"); int rank = (int) field.get(customer);
在使用反射獲取被調用類的構造方法、方法或變量,可能對於調用類是不可訪問的,如被調用類的"private"構造方法,"private" 方法, "private" 變量,會拋出 IllegalAccessException。
java能夠經過使用 "AccessibleObject#setAccessible(boolean flag)" 改變可訪問性。
"Constructor"、"Method" 和 "Field" 都是 "AccessibleObject" 的子類。
eg:
//在VipCustomer中定義類靜態常量PRI_NO=100 Field field = getVipCustomerClass().getDeclaredField("PRI_NO"); field.setAccessible(true); Assert.assertEquals(100, field.get(null)); //私有構造方法 Constructor<VipCustomer> constructor = getVipCustomerClass().getDeclaredConstructor(); constructor.setAccessible(true); VipCustomer customer = constructor.newInstance(); Assert.assertNull(customer.getCustomerNo()); Assert.assertNull(customer.getName()); Assert.assertNull(customer.getMobilePhone()); //調用私有類方法 Method method = getVipCustomerClass().getDeclaredMethod("doNothingByVipCustomer"); method.setAccessible(true); method.invoke(null);
數組是比較特殊的類型。
10.1) Array#newInstance(Class<?> componentType, int length),建立一維數組,eg:
//一維數組 Object array = Array.newInstance(String.class, 2); Array.set(array, 0, "小ben馬"); Array.set(array, 1, "xiaobenma"); Assert.assertEquals("小ben馬", Array.get(array, 0)); Assert.assertEquals("xiaobenma", Array.get(array, 1));
10.2) Array#newInstance(Class<?> componentType, int... dimensions),建立多維數組,eg:
//多維數組 //String[2][1] Object arrays = Array.newInstance(String.class, 2, 1); Object array0 = Array.newInstance(String.class, 1); Array.set(array0, 0, "小ben馬"); Array.set(arrays, 0, array0); Object array1 = Array.newInstance(String.class, 1); Array.set(array1, 0, "xiaobenma"); Array.set(arrays, 1, array1); Assert.assertEquals("小ben馬", Array.get(Array.get(arrays, 0), 0)); Assert.assertEquals("xiaobenma", Array.get(Array.get(arrays, 1), 0));
10.3)Array#get(Object array, int index)
根據數組和相關索引獲取對應的值
10.4)Array#set(Object array, int index, Object value)
根據索引和相關索引,設置對應的值
一般在類中
"Member#getModifiers()" 返回一個int類型,經過解釋int的值,能獲取定義的修飾符列表。"Constructor"、"Method" 和 "Field" 都是 "Member" 的實現類。
修飾符返回的int值,須要經過 "Modifier" 解析。
其中,
若是你看過Modifier
的源碼,你會發現一個有趣的事情,修飾符是按bit
位定義的,如:
/** * The {@code int} value representing the {@code public} * modifier. */ public static final int PUBLIC = 0x00000001; /** * The {@code int} value representing the {@code private} * modifier. */ public static final int PRIVATE = 0x00000002; /** * The {@code int} value representing the {@code protected} * modifier. */ public static final int PROTECTED = 0x00000004;
java.lang.reflect
Proxy
是反射中比較重要的應用,在後續博客單獨更新。