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