JAVA反射机制是在运行状态中, 对于任意一个类(class文件), 都能够知道这个类的所有属性和方法; 对于任意一个对象, 都能够调用它的任意一个方法和属性; 这种动态获取的信息以及动态调用对象方法的功能称为java语言的反射机制。
动态获取类中信息, 就是java反射。 可以理解为对类的解剖。
如果想要对指定名称的字节码文件进行加载并获取其中的内容并调用, 这时就使用到了反射技术。
得到各字节码对应的实例对象(Class类型)的3种方法:
1. 类名.class。例如,System.class
2. 对象.getClass()。例如,new Date().getClass()
3. Class.forName(“类名”)。例如,Class.forName(“java.util.Date”)
String str1 = "abc";
Class cls1 = str1.getClass();
Class cls2 = String.class;
String cls3 = Class.forName("java.lang.String");
System.out.println(cls1 == cls2);
System.out.println(cls1 == cls3);
System.out.println(cls1.isPrimitive()); //false
System.out.println(int.class.isPrimitive()); //true
System.out.println(int.class == Integer.class); //false
System.out.println(int.class == Integer.TYPE); //true
//Integer.TYPE代表所包装的基本类型的字节码
System.out.println(int[].class.isPrimitive()) //false
System.out.println(int[].class.isArray()) //false
数组类型的Class实例对象
Class.isArray()
总之,只要是在源程序中出现的类型,都有各自的Class实例对象。例如:int[],void。
反射就是把Java类中的各种成分映射成相应的Java类。
Constructor类
代表某个类中的一个构造方法。
得到某个类所有的构造方法:
Constructor[] constructors = Class.forName("java.lang.String").getConstructors();
得到某一个构造方法:
Constructor constructor1 = Class.forName("java.lang.String").getConstructor(StringBuffer.class);
创建实例对象
通常方式:String str = new String(new StringBuffer(“abc”));
反射方式:String str = (String)constructor.newInstance(new StringBuffer(“abc”));
Class.newInstance()方法
String obj = (String)Class.forName(“java.lang.String”).newInstance();
该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。
该方法内部用到了缓存机制来保存默认构造方法的实例对象。故反射是比较耗时的操作。
Constructor constructor1 = String.class.getConstructor(StringBuffer.class);
String str2 = (String) constructor1.newInstance(new StringBuffer("abc"));
System.out.println(str.charAt(2)); //打印结果是c
Field类
public class ReflectPoint {
private int x;
public int y;
public String str1 = "ball";
public String str2 = "basketball";
public String str3 = "itcast";
public ReflectPoint(int x, int y) {
super();
this.x = x;
this.y = y;
}
@Override
public String toString() {
return str1 + ":" + str2 + ":" +str3;
}
}
ReflectPoint pt1 = new ReflectPoint(3, 5);
Field fieldY = pt1.getClass().getField("y"); //fieldY是类的一个字段,而非具体对象身上的字段
System.out.println(fieldY.get(pt1)); //打印结果是5
Field fieldX = pt1.getClass().getDeclaredField("x"); //可以访问private对象
fieldX.setAccessible(true) //设置可以访问(暴力反射)
System.out.println(fieldX.get(pt1)); //打印结果是3
changeStringValue();
private static void changeStringValue(Object obj) throws Exception {
Field[] fields = obj.getClass().getFields();
for(Field field: fields) {
if(field.getType() == String.class) { //比较同一字节码,用“==”
String oldValue = (String)field.get(obj);
String newValue = oldValue.replace('b', 'a');
field.set(obj, newValue);
}
}
}