反射技术透彻解析
在我们学习框架的时候,一讲框架的原理就经常会用到reflect(反射技术)。
下面我想复习一下反射技术。
什么是反射?
反射就是将一个类的一些元素(包名,类名,属性,方法,构造器)映射成为相对应的类。
这句话是网上看来的。想想非常形象。
下面我通过案例说说这个反射技术.
首先要明白一个类要反射首先要得到一个类的字节码。说白了就是或得该类的类名。然后通过类名获取到你想要类中的一些元素。然后把这些元素作用于那个对象。这是我对反射的理解。
下面我有一个person.java这个类。我现在相对该类通过构造器创建对象。创建完对象后发现我初始值的时候我不想要了想重新赋值该怎么办呢。我们通过反射来实现。
packagecom.fish;
public class Person {
publicString name;
privateString address;
public String getName(){
return name;
}
public void setName(String name) {
this.name = name;
}
publicString getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
publicPerson(String name, String address) {
super();
this.name = name;
this.address = address;
}
}
这就是一个最简单的javabean。然后我们写Test类。
package com.fish;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Test {
publicstatic void main(String[] args) throws Exception {
//我们获得构造器。参数表示你构造器里面的参数的类型。从person类我们可以知道我的构造器里面也有两个参数,类型都是string的
Constructor<Person>con = Person.class.getConstructor(String.class,
String.class);
//下面这句话搞完我们就已经得到了person对象了。
Personp = (Person) con.newInstance("fish", "杭州");
//同理我们可以利用这个方式获取类中的属性。这里我想说,p.getClass()和Person.Calss和Class.forName(“com.fish.Person”)都是一样的,就是获取person的字节码。里面的field方法的参数表示的是属性的名字。
Fieldfieldname = p.getClass().getField("name");
//上面我们只是得到了类的属性,但是不是对象的属性,所以要将这个属性作用到你要的对象上。显然p是我们的对象
System.out.println(fieldname.get(p));
//当然我们也可以得到adress属性,但是看看类中address是私有的,所以我们必须通过暴力反射开启我们对私有权限的读写。所以我们通过.setAccessible开启。
Fieldfieldaddress = p.getClass().getDeclaredField("address");
fieldaddress.setAccessible(true);
System.out.println(fieldaddress.get(p));
//前面说了我们说创建对象后我们不想要原来通过构造器初始化的值了,所以我们可以通过暴力反射来改变,我想我属性中所有i的字母改成a,也就是所fish值我要改成fash。通过change()我们先去看change。
change(p);
//同理我们把属性换了我们要通过一个getName函数查看了。实现原来和上面的相同。两个参数是第一个是方法名字。第二是参数,因为getName没有参数,所以我写空。
然后我们通过invoke调用这个类对应的对象。因为没有参数所以给的值也就是null、我们可以看到结果是fash而不是fish
Methodmethod = Person.class.getMethod("getName", null);
System.out.println(method.invoke(p,null));
}
privatestatic void change(Person p) throws Exception {
//因为一个类中有多个属性所以我们定义一个属性的数组。
Field[] field = p.getClass().getFields();
for(Field i : field) { //然后通过增强for循环来迭代这个属性。
if(i.getType() == String.class) {
//首先判断你的属性是不是string类型的,如果是那么我们获取这个类属性的值,并读取其对象的值。
Stringoldvalue = (String) i.get(p);
//读取了我们通过系统自己定义的替换函数,将其替换。替换完以后当然我们当然要把这个值赋给该对象的属性。
Stringnewvalue = oldvalue.replace('i', 'a');
i.set(p,newvalue);
}
}
}
}