1、什么是反射?
反射是将 java 类信息、方法信息 或者 字段信息包装为一个特定的实例化对象,通过这些对象内部方法的调用,可以达到使用java类功能的效果。
下面用一个Parent类来说明反射如何使用。
public class Parent {
public static String city = "成都";
private int age = 23;
protected int heveay = 56;
public String name = "小明";
public Parent(){
System.out.println("无参构造方法");
}
public Parent(String s){
System.out.println("这是有参构造方法:" + s);
}
protected int execute(){
System.out.println("这是执行方法");
return 100;
}
private int execute2(String a){
System.out.println("这是执行方法" + a);
return 100;
}
}
2、获取类对象
1、Class cla = Class.forName("Parent"); 比如获取Parent类的类对象,当找不到名为 Parent 的类时,会抛出一个异常 ClassNotFoundException。
2、Parent p = new Parent(); Class cla = parent.getClass(); 利用一个实例化对象的getClass() 方法获取类对象。
3、Class cla = Parent.class; 用类.class 的方法获取类对象。
构造实例化对象:Object o = cla.newInstance(); Parent parent = (Parent) o; 只能调用默认构造方法去实例化对象。
3、获取构造方法对象
Constructor constructor = cla.getConstructor(); 获取构造方法对象,默认是无法构造方法对象,如果找不到对应的构造方法,就抛出异常 NoSuchMethodException。
Constructor constructor = cla.getConstructor(String.class); 获取参数为String的构造方法对象。如果找不到对应的构造方法,就抛出异常 NoSuchMethodException。
构造实例化对象。
Object o = constructor.newInstance("小蓝"); Parent parent = (Parent) o;
4、获取成员变量对象
4.1、静态成员变量
Field field = cla.getDeclaredField("city");
System.out.println(field.getName()); 输出变量名字 city
System.out.println(field.get(field.getName())); 输出变量值 成都
因为静态变量是属于类的,类信息里面就已经包含了静态变量的信息,包括变量值。
4.2、public 成员变量
Parent parent = (Parent) cla.newInstance();
Field field = cla.getField("name");
System.out.println(field.get(parent)); 输出name变量的值 小明
4.3、protected 、private 成员变量
Field field = cla.getDeclaredField("heveay");
field.setAccessible(true); //设置允许访问这个变量
System.out.println(field.get(parent)); 输出heveay变量值 56
Field field = cla.getDeclaredField("age");
field.setAccessible(true); 设置允许访问这个变量
System.out.println(field.get(parent)); 输出age变量的值 23
5、获取成员方法对象
5.1、public 方法
Parent parent = (Parent) cla.newInstance();
Method method = cla.getMethod("execute"); 这是无参方法
method.invoke(parent); 这是无参方法的执行
如果是有参方法的话,比如 execute(String a) ,那就应该是 Method method = cla.getMethod("execute", String.class);
method.invoke(parent, "hello");
5.2、private 、protected 方法
Parent parent = (Parent) cla.newInstance();
Method method = cla.getDeclaredMethod("execute2", String.class);
method.setAccessible(true);
method.invoke(parent, "hello");
特别说一下,getFiled 只能用于获取public 变量, getDeclaredField 可以用于获取public、private 、protected 变量。 getMethod 只能用于获取public 方法,getDeclaredMethod 可以用于获取public、private 、protected 方法。
如果是private、protected,需要设置 setAccessible(true) 来允许访问。
6、设置变量的值
6.1、设置public 变量值
Parent parent = (Parent) cla.newInstance();
Field field = cla.getField("name");
field.set(parent, "花里胡哨"); 设置变量值
System.out.println(field.get(parent)); 输出变量值 花里胡哨
6.2、设置 protected 、private 变量值
Parent parent = (Parent) cla.newInstance();
Field field = cla.getDeclaredField("name");
field.setAccessible(true) ;
field.set(parent, "花里胡哨");
System.out.println(field.get(parent));