- 反射的基石:Class类
- Class类描述了类的名字,访问属性,属于的包名,字段名称的列表,方法名称的列表等信息
- 如何得到各个字节码对应的实例对象(Class类实例)?
- 类名.class
- 对象.getClass();
- Class.forName("类名(包括包名)");
- 基本数据类型.class.isPrimitive()返回true
- int.class==Integer.TYPE返回true
- 反射
- 一个Java类用一个Class类的对象表示
- Class类提供方法来获得Java类的信息。Field, Method, Constructor, Package等等。
- 学习反射的要点是获得这些对象之后如何用
- Constructor类
- 得到某个类的所有构造方法:Constructor[] cons = Class.forName("java.lang.String").getConstructors();
- 得到某个类的某个构造方法:Constructor con = Class.forName("java.lang.String").getConstructor(StringBuffer.class);
- 创建实例对象:
- 通常方式:String s = new String(new StringBuffer("abc"));
- 反射方式:String s = (String)constructor.newInstance(new StringBuffer("abc"));
- Class.newInstance方法:
- String s = (String)Class.forName("java.lang.String").newInstance();
- 该方法内部先得到默认的构造方法
- Field类:
- 示例:获取一个对象中的成员值并且把对象中所有String类的成员变量中的b改成a
public class ReflectPoint {
private int x;
public int y;
public String str1 = "abandon";
public String str2 = "basketball";
public String str3 = "binbow";
public ReflectPoint(int x, int y){
this.x = x;
this.y = y;
}
public String toString(){
return str1 + " " + str2 + " " + str3;
}
}
//主类:
import java.lang.reflect.*;
public class ReflectFieldDemo {
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
ReflectPoint rp = new ReflectPoint(3,5);
//私有成员x:
Field fieldX = rp.getClass().getDeclaredField("x");
fieldX.setAccessible(true); //因为私有所以要强行获取
System.out.println("x = " + fieldX.get(rp));
//公有成员y:
Field fieldY = rp.getClass().getField("y");
System.out.println("y = " + fieldY.get(rp));
//改变对象中String成员的方法:
changeLetter(rp);
System.out.println(rp);
}
//改变类的对象中String成员,将b换成a的方法:
public static void changeLetter(Object obj) throws Exception{
Field[] fields = obj.getClass().getFields();
for(Field field:fields){
if(field.getType() == String.class){
String oldV = (String)field.get(obj);
String newV = oldV.replace('b', 'a');
field.set(obj, newV);
}
}
}
}
- 示例:获取一个对象中的成员值并且把对象中所有String类的成员变量中的b改成a
- Method类
- 得到类中的某一个方法: Method methodCharAt = Class.forName("java.lang.String").getMethod("charAt", int.class);
- 调用方法: methodCharAt.invoke(str, 1);
- 如果invoke的第一个参数为null,说明该方法是静态方法
- 数组的反射
- 具有相同维数和元素类型的数组属于同一个类型,既具有相同的Class类对象
- 代表数组的Class类实例对象的getSuperClass方法返回的父类为Object对应的Class
- 基本类型的一维数组可当做Object,不可当做Object[];非基本类型的一维数组都可。
- Arrays.asList()方法处理int[]和String[]时的差异
- Array工具类用于完成对数组的反射操作(java.lang.reflect.Array)