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());
	}
}


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