反射机制:对于一个类在运行状态中能够知道这个类所有的属性与方法,对于一个对象能够调用它任意的方法与属性,也就是动态操纵java程序的能力。反射机制可以跳过权限去调用对象甚至改造对象(比如获取private成员),功能是比较强大的。
1.获取class类型对象实例
class类型对象保存了类属性的描述信息。
package test;
import java.lang.reflect.*;
import java.util.Arrays;
public class Test06 {
private int a=0;
public Test06(int a) {
this.a = a;
}
public Test06() {
}
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Test06 test06=new Test06();
//方法一 getClass()
Class cl = test06.getClass();
System.out.println(cl.getName());
System.out.println(cl.getClass().getName());
System.out.println("===================");
System.out.println(test06.getClass());
System.out.println(test06.getClass().getName());
System.out.println("===============");
//方法二 Class.forName()
String s1="test.Test06";
Class cl2 = Class.forName(s1);
System.out.println(cl2);
System.out.println(cl2.getName());
System.out.println("===============");
//方法三 int.class(类型.class)
Class cl3 = int.class;
System.out.println(cl3);
System.out.println(cl3.getName());
System.out.println("================");
Class cl4 = Class.forName("test.Test06"); //获得Class类型对象实例
//利用反射和无参构造器创建对象
Test06 o1 = (Test06) cl4.getConstructor().newInstance();
System.out.println(o1.a);
//利用反射和有参构造器创建对象
Test06 o2 = (Test06) cl4.getConstructor(int.class).newInstance(10);
System.out.println(o2.a);
}
}
2.获取类的属性与方法
//利用反射分析类的能力——检查类的结构
class ReflectionTest{
private int a;
protected int b;
public int c;
public ReflectionTest() {
}
public ReflectionTest(int a,int b,int c) {
this.a = a;
this.b = b;
this.c = c;
}
private void t1(){
System.out.println("ok");
}
public int getB(){
return b;
}
public void setB(int b){
this.b=b;
}
public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException, IllegalAccessException {
Class rTestClass = ReflectionTest.class; //获取Class类型对象实例
/*ReflectionTest reflectionTest = new ReflectionTest();
Class aClass = reflectionTest.getClass();*/
//1.利用反射获取对象字段描述
Field[] fields = rTestClass.getFields(); //获取类所有公共字段,包括继承自超类的
Field[] declaredFields = rTestClass.getDeclaredFields(); //获取类所有字段,包括私有的、受保护的,不包括超类的
//Field a = rTestClass.getField("a");不能使用getField访问私有字段
Field a = rTestClass.getDeclaredField("a"); //获取指定字段描述
System.out.println(a+" "+"private修饰符描述值:"+a.getModifiers());
Field b = rTestClass.getDeclaredField("b"); //获取指定字段描述
System.out.println(b+" "+"protected修饰符描述值:"+b.getModifiers());
Field c = rTestClass.getDeclaredField("c"); //获取指定字段描述
System.out.println(c+" "+"public修饰符描述值:"+c.getModifiers());
for (Field field : declaredFields) {
System.out.println(field);
System.out.println("字段的值:"+field.get(new ReflectionTest(7,8,9))); //获取指定对象中字段的值
System.out.println("字段名:"+field.getName()); //getName()获得字段名
//getModifiers()获得修饰符的描述返回值,isPrivate()分析返回值,判断修饰符
System.out.println("字段修饰符是否为private:"+ Modifier.isPrivate(field.getModifiers()));
System.out.println("字段类型:"+field.getType());
System.out.println("是否为volatile修饰:"+Modifier.isVolatile(field.getModifiers()));
}
System.out.println("===============================");
//2.利用反射获取对象方法描述
Method[] methods = rTestClass.getMethods(); //获取类所有公共方法,包括继承自超类的
Method[] declaredMethods = rTestClass.getDeclaredMethods(); //获取类所有方法,包括私有的、受保护的,不包括超类的
Method setB = rTestClass.getDeclaredMethod("setB", int.class); //获取指定名方法
System.out.println(setB);
for (Method method : declaredMethods) {
System.out.println(method);
System.out.println("方法名:"+method.getName());
System.out.println("方法访问修饰符值:"+method.getModifiers());
System.out.println("是否为public:"+Modifier.isPublic(method.getModifiers()));
System.out.println("方法参数类型:"+ Arrays.toString(method.getParameterTypes()));
System.out.println("方法返回值类型:"+method.getReturnType());
}
System.out.println("=============================");
//3.利用反射获取对象构造器描述
Constructor[] constructors = rTestClass.getConstructors(); //获取类所有公共构造器
Constructor[] declaredConstructors = rTestClass.getDeclaredConstructors(); //获取类所有的构造器
Constructor constructor = rTestClass.getDeclaredConstructor(int.class, int.class, int.class); //获取指定参数类型的构造器描述
System.out.println(constructor);
for (Constructor declaredConstructor : declaredConstructors) {
System.out.println("构造器名称:"+declaredConstructor.getName());
System.out.println("方法访问修饰符值:"+declaredConstructor.getModifiers());
System.out.println("是否为public:"+Modifier.isPublic(declaredConstructor.getModifiers()));
System.out.println("参数类型:"+Arrays.toString(declaredConstructor.getParameterTypes()));
}
}
}
3.利用反射动态操纵类对象
class MyTest{
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException {
//利用反射修改类
//1.利用反射创建对象
Class testClass = ReflectionTest.class;
ReflectionTest test = (ReflectionTest) testClass.getConstructor(int.class, int.class, int.class).newInstance(10, 20, 30);
System.out.println("b==>"+test.getB());
System.out.println("=======================");
//2.修改对象成员字段
Field a1=testClass.getDeclaredField("a");
a1.setAccessible(true); //private字段需开启访问权限,否则会出现java.lang.IllegalAccessException异常
Object v = a1.get(test); //获取字段的值
System.out.println("修改前的值:"+v);
a1.set(test,50);
System.out.println("修改后的值:"+a1.get(test));
System.out.println("===================");
//3.修改对象成员方法
Method getB = testClass.getDeclaredMethod("getB");
int invoke = (int) getB.invoke(test); //使用invoke执行方法
System.out.println("b==>"+invoke);
Method setB = testClass.getDeclaredMethod("setB", int.class);
System.out.println("setB()返回值"+setB.invoke(test,60)); //设置方法参数值并执行方法
System.out.println("执行方法后b==>"+getB.invoke(test));
System.out.println("==============================");
}
}