反射的原理:
第一步:首先,把java类保存到本地硬盘.java文件里面
第二步:编译为.class文件
第三步:通过JVM(虚拟机)使用类加载器把.class文件加载到内存中,
class文件在内存中可以通过Class类进行表示,得到Class类对象就可以得到java类中的所有东西。
(这里的东西包括类里面的参数,构造方法,以及普通方法)
获取Class类的三种方式:
Class clazz1 = Person.class;
Class clazz2 = new Person().getClass();
Class clazz3 = Class.forName("cn.itcast.FanShe.Person");
首先写一个类测试一下:
public class Person {
private String name;
private String id;
public Person() {
}
public Person(String name, String id) {
this.name = name;
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
操作无参数的构造方法
// 得到Class
Class c1 = Class.forName("cn.itcast.FanShe.Person");
// 得到Person类的实例
Person p = (Person) c1.newInstance();
p.setName("zhangsan");
System.out.println(p.getName());
操作有参数的构造方法
//得到Class
Class c2 = Class.forName("cn.itcast.FanShe.Person");
//使用有参的构造方法
//c1.getConstructors()得到所有的构造方法
//对此可以使用getConstructor(Class... parameterTypes)方法
//里面的参数类型使用class形式传递
Constructor cs = c2.getConstructor(String.class,String.class);
//通过有参数的构造方法设置值
Person p = (Person) cs.newInstance("lisi","1234");
System.out.println(p.getName()+"+"+p.getId());
操作name属性
//得到Class
Class c3 = Class.forName("cn.itcast.FanShe.Person");
//得到Person的实例化对象
Person p1 = (Person) c3.newInstance();
//得到name属性
//c3.getDeclaredFields()得到所有属性
Field f1 = c3.getDeclaredField("name");
//设置可以操作私有属性
f1.setAccessible(true);
//设置name值
//Field对象的set(Object obj, Object value)方法
//第一个参数是操作的对象,第二个参数是对对象赋的值
f1.set(p1, "wangwu"); //相当于p.name = "wangwu";
System.out.println(f1.get(p1));
操作普通方法
//得到Class
Class c4 = Class.forName("cn.itcast.FanShe.Person");
//得到Person的实例化对象
Person p1 = (Person) c4.newInstance();
//得到普通方法
//c4.getDeclaredMethods(),表示得到所有普通方法
Method m1 = c4.getDeclaredMethod("setName",String.class);
//invoke方法让setName方法执行,执行设置值
//如果操作的方法是private私有的
//就要用m1.setAccessible(true);
m1.invoke(p1, "xiaoliu");
System.out.println(p1.getName());
|
|