Java 學習筆記——反射

1. Class 類

    Class 類用於保存虛擬機運行時的類型信息。創建 Class 類對象的三種方式:
    1)getClass()

Employee e = new Employee("Harry Hacker");
Class<?> cl = e.getClass();

    2)Class.forName()

try {
	Class<?> cl = Class.forName("study.JavaSE.Employee");
	System.out.println(cl.getName());
} catch (ClassNotFoundException e) {
	e.printStackTrace();
}

    3)類名.class

Class<?> cl = Employee.class;

2. Class 類的 newInstance() 創建對象

try {
	Class<?> cl = Class.forName("study.JavaSE.Employee");
	Employee e = (Employee) cl.newInstance();
	e.setName("Harry Hacker");
	System.out.println(e.getName());
} catch (ClassNotFoundException e) {
	e.printStackTrace();
} catch (InstantiationException | IllegalAccessException e) {
	e.printStackTrace();
}

    class 類的 newInstance() 方法調用的是類的無參構造方法
3. 使用 Constructor 類創建對象

try {
	Class<?> cl = Class.forName("study.JavaSE.Employee");
	Constructor<?> constructor = cl.getConstructor(String.class);
	Employee e = (Employee) constructor.newInstance("Harry Hacker");
	System.out.println(e.getName());
} catch (Exception e) {
	e.printStackTrace();
}

    Constructor 類的 newInstance() 方法可以通過類的帶參數的構造方法創建對象。
    Class 類的 getFields()、getMethods()、getConstructors() 方法分別返回類提供的 public 域、方法和構造器數組,包括超類的共有成員,而 Class 類的 getDeclaredFields()、getDeclaredMethods()、getDeclaredConstructors() 方法返回類中聲明的全部域、方法和構造器,包括 private 和 protected 成員,但不包過父類的成員。
4. 設置對象屬性值

Manager harry = new Manager("Harry Hacker");
Class<?> cl = harry.getClass();
try {
	Field f = cl.getDeclaredField("buddies"); //獲取屬性名爲 buddies 的屬性對象
	f.setAccessible(true); //抑制 Java 訪問控制
	Object v = f.get(harry); //獲取屬性值
	System.out.println(v);
			
	f.set(harry, 1); //設置屬性值
	v = f.get(harry);
	System.out.println(v);
} catch (Exception e) {
	e.printStackTrace();
}
5. 調用方法
    可以通過 Method 類的 invoke() 方法實現對反射對象的方法調用。
Class<?> cl = Manager.class;
Manager harry = new Manager("Harry Hacker");
try {
	Method m = cl.getDeclaredMethod("setBuddies", Integer.class); //獲取方法名爲 setBuddies,參數類型是 Integer 的方法對象
	m.invoke(harry, 50); //調用方法,invoke 方法第一個參數表示操作的對象,第二參數表示所調用方法傳入的參數
	System.out.println(harry.getBuddies());
			
	m = cl.getDeclaredMethod("getBuddies"); //獲取無參的方法對象
	int n = (Integer)m.invoke(harry);
	System.out.println(n);
			
	m = cl.getDeclaredMethod("printStaticMethod");
	m.invoke(null); //調用靜態方法
			
	m = cl.getDeclaredMethod("printStaticMethod", String.class);
	m.invoke(null, "");  //調用帶參數的靜態方法
} catch (Exception e) {
   e.printStackTrace();
}

6. 反射泛型數組

      java.lang.reflect 包中的 Array 類 newInstance() 方法可以動態的創建數組。java.utils 包下的 Arrays 類的 copyOf() 方法實現就是應用了 Array.newInstance() 方法。

public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
        @SuppressWarnings("unchecked")
        T[] copy = ((Object)newType == (Object)Object[].class)
            ? (T[]) new Object[newLength]
            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }

7. 反射應用實例

import java.lang.reflect.Field;

public class BasicModel {
	private static String getString(Object o, Class< ? > c){
		String res = "";
		Field[] fields = c.getDeclaredFields();
		
		if(c.getSuperclass() != BasicModel.class){
			res += getString(o, c.getSuperclass()) + ", ";
		}
		
		for(Field field : fields){
			field.setAccessible(true);
			try {
				res += field.getName() + " = " + field.get(o) + ", ";
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} 
		}
		return res.substring(0, (res.length() - 2 < 0 ? 0 : res.length() - 2));
	}
	
	public String toString(){
		return BasicModel.getString(this, this.getClass());
	}
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章