JAVA 反射(Reflection)是指程序可以访问、检测和修改它自身状态或行为的能力。
反射分为几种:
Class类(java.lang.Class)
获取构造器 Constructor
获取成员变量 Field
获取方法 Method
获取数组 Array
Class类(java.lang.Class)
说白了,就是 反射的入口:
解释如下:
1.Class是反射操作的入口。
2.每个加载到内存的对象,JVM都会实例化一个Class的对象来描述它。
3.Class的对象反射它所表示的对象。
4.Class对象存储的被反射类的信息包括:
类名
继承性
实现的接口
方法
成员
假如我现在有一个Mother 类
public class Mother {
/*
定义 Mother 类及其属性(身高、体重、年龄)和方法(工作、做家务);
*/
private String high;
private String weight;
private String age;
Mother(){
}
Mother(String high,String weight,String age){
this.high = high;
this.weight = weight;
this.age = age;
System.out.println("反射构造函数");
System.out.println(high+" | "+weight+" | "+age);
}
public void setWeight(String weight) {
this.weight = weight;
}
public void setHigh(String high) {
this.high = high;
}
public void setAge(String age) {
this.age = age;
}
public void getAge(){
System.out.println(this.age);
}
public void getHigh() {
System.out.println(this.high);
}
public void getWeight() {
System.out.println(this.weight);
}
public void work(){
}
public void homework(){
}
}
我先获得Class 类 三种方法: 第三种*** 代表 类的路径
Class cls = Mother.class;
Class cls = new Mother().getClass();
Class cls = Class.forName("****");
当获得class 后 ,开始获取构造器
获取构造器 Constructor
Class cls = new Mother().getClass();
Constructor constructor[] = cls.getDeclaredConstructors();
try {
constructor[1].setAccessible(true);
Object object = constructor[1].newInstance(new Object[]{"A","B","C"});
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
获取构造器集合, 并设置访问权限.
对构造器利用Object 进行实例化一个对象,设置身高为 A ,体重为 B ,年龄为 C
结果如下:
获取成员变量 Field
获取成员变量:
每个成员变量有类型和值。
java.lang.reflect.Field
为我们提供了获取当前对象的成员变量的类型,和重新设值的方法。
获取变量的类型
类中的变量分为两种类型:基本类型和引用类型:
- 基本类型( 8 种)
- 整数:byte, short, int, long
- 浮点数:float, double
- 字符:char
- 布尔值:boolean
- 引用类型
- 所有的引用类型都继承自 java.lang.Object
- 类,枚举,数组,接口都是引用类型
- java.io.Serializable 接口,基本类型的包装类(比如 java.lang.Double)也是引用类型
java.lang.reflect.Field
提供了两个方法获去变量的类型:
- Field.getType():返回这个变量的类型
- Field.getGenericType():如果当前属性有签名属性类型就返回,否则就返回
Field.getType()
获取任意指定名字的成员
public Field getDeclaredField(String fieldName)
获取全部存到集合中的话:
Field []field = cls.getDeclaredFields();
实例:
我现在 反射构造器 将 Mother 类中 high 设置为 "A" , weight 设置为 "B" , age 设置为 5 ;
通过反射集合 获取所有的私有变量. (私有和保护类型的必须设置 可访问权限 : .setAccessible(true);)
然后输出 反射得到的 变量类型,名称以及 值.
try {
constructor[1].setAccessible(true);
Mother mother = (Mother) constructor[1].newInstance("A","B",5);
Field []field = cls.getDeclaredFields();
for( Field fieldidex: field){
fieldidex.setAccessible(true);
System.out.println("field -> type: "+fieldidex.getType()+" name: "+fieldidex.getName() + " value : "+
fieldidex.get(mother));
} } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); }
获取方法 Method
获得 类中的方法, 并 调用 类成员方法, 进行修改
实例:
用 method 获取 setAge 方法, 并调用 invoke 实现 调用 setAge 方法 进行 数值修改
try {
constructor[1].setAccessible(true);
Mother mother = (Mother) constructor[1].newInstance("A","B",5);
Field []field = cls.getDeclaredFields();
for( Field fieldidex: field){
fieldidex.setAccessible(true);
System.out.println("field -> type: "+fieldidex.getType()+" name: "+fieldidex.getName());
if (fieldidex.getName()=="age"){
System.out.println("value : "+fieldidex.getInt(mother) );
}
}
Method method = cls.getDeclaredMethod("setAge", int.class);
method.invoke(mother,20);
System.out.println("field -> after change : type: "+field[2].getType()+" name: "+field[2].getName() +" value : "+field[2].getInt(mother));
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
123