------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------
- 讲反射之前先了解一下Class类:
- Class是一个类,代表一类事物,但他不管着各类有什么方法或属性。
- Class cls=内存里的字节码,这个字节码是由类加载到内存产生的,因此每份字节码都是各自类的对象,例如Class cls=Date.class表示Date类在内存里的字节码,而这个字节码又是对象,这个对象的类是Class。
- Class.forname(String addreess)的作用是返回字节码,返回的方式有两种,第一种是这份字节码曾经加载过,已经在java虚拟机里边了,直接返回。第二种是java虚拟机里还没有这份字节码,则用类加载器去加载,把加载进来的字节码缓存在虚拟机里,然后返回。
- 得到字节码的方式有三种: 类.class 、 对象.getClass() 和 Class.forName(“类的完整路径”),如果在写源程序时还不知道想要的类叫什么,就用第三种方式得到字节码,将“类的完整路径”用变量表示,当程序运行时从一个配置文件里将类的名字传进来,这样就可以解决前两种方式在没有类名时无法使用的问题。
- 除了八种基本数据类型,void也有自己对应的字节码void.class,所以有九个预定义的class字节码。
- Syso(Integer.class==int.class)返回的是false,说明Integer和int的字节码是不相同的。
- Syso(Integer.TYPE==int.class)返回的是true,其中TYPE的作用是返回Integer所包装的基本类型的字节码。
- isPrimitive()返回是否是原始类型,int.class.isPrimitive()返回true。String和int [] 都不是原始类型,所以返回false.
- 判断一个Class对象是不是数组,用isArray()方法,int [].class.isArray()返回true.
- 总之,只要在源程序中出现类型,都有与其相对应的Class实例对象。
- 反射:
- //用反射的到同样的效果:new String(new StringBuffer(“abc”))
- Constructor cons=String.class.getConstructor(StringBuffer.class)
- //编译时cons并不知道是String类,编译器只看变量的定义,不看代码的执行,在运行时才知道,要区分开编译时和运行时
- String str=(String)cons.newInstance(new StringBuffer(“abc”));
- 之所以在newInstance()返回值前加上强制转换是因为返回的是Object。
- 注:即使这样定义,String str=(String)cons.newInstance(“abc”);编译时是不会报错,编译器只是想代码翻译成二进制数,只有在运行时才报错,参数无匹配。
- 用Class.newInstance()创建不带参数的构造方法,例如String obj=(String)Class.forName(“java.lang.String”).newInstance(),该方法内部首先得到默认的构造方法,然后用该构造方法创建对象。该方法的内部具体代码用到了缓存机制来保存默认构造方法的实例对象。
- 反射会导致程序性能严重下降。
- 将ReflectPoint中的非私有属性的字符b改为a.
public class ReflectPoint {
public String str1 = "ball"; //定义公共的String字符串。
public String str2 = "basketball";
public String toString() {
return str1 + "\t" + str2;
}
}
import java.lang.reflect.Field;
public class ChangeValue {
public static void main(String[] args) throws Exception {
ReflectPoint rp=new ReflectPoint();
//调用changeStringValue()方法,参数为ReflectPoint对象
changeStringValue(rp);
System.out.println(rp);
}
private static void changeStringValue(Object obj)throws Exception{
//用对象反射得到对应类的所有非私有属性
Field fields[]=obj.getClass().getFields();
//循环改变属性的值
for(Field field:fields){
//判读属性的字节码是否为String型,此处不能用equals
if(field.getType()==String.class){
//将得到的Object型强转为String类存到oldValue中
String oldValue=(String)field.get(obj);
//替换oldValue中的'b'为'a'存到newString 中
String newValue=oldValue.replace('b', 'a');
//对传进来的obj对象的field字段进行设置
field.set(obj, newValue);
}
}
}
}