赞
踩
作者 | ewenll
责编 | 夕颜
出品 | CSDN博客
Java代码在计算机中经历的阶段:三个阶段 Person.java经过javac编译,变为Person.class文件(字节码文件),字节码文件中,主要有类的属性、构造函数、方法,当然还有类的其他信息,这个阶段称为源码阶段,通过类加载器进入内存,在内存中生成一个Class对象,这个阶段为Class类对象阶段,一个类的Class对象中存储了类的全部信息,使用这个类对象的阶段称为Runtime运行时阶段 Java识别类和对象信息的两种方式//ewen包下的Person类public class Person {private String name;private int age;public String a;protected String b;String c;private String d;//构造函数、get、set方法省略。public void sleep(){ System.out.println("sleep...."); }}
public class ReflectTest {public static void main(String[] args) throws Exception {//获取Person类的Class对象// 通过类名.class获取 Class clazz1 = Person.class;//通过Class.forName("类的全路径名") Class clazz2 = Class.forName("ewen.Person");//通过对象名.getClass()方法获得 Person person = new Person(); Class clazz3 = person.getClass(); System.out.println(clazz1 == clazz2); //true System.out.println(clazz2 == clazz3); //true }}
一个类只有一个Class实例,无论通过哪种方式获取,得到的都是同一个Class对象。
Class对象的功能
1)获取类的成员变量
//获取所有pubic修饰的成员变量 Field[] fields = clazz1.getFields();for (Field field : fields) { System.out.println(field); //public java.lang.String ewen.Person.a,只有a是public修饰的 }//获取指定的成员变量 Field field = clazz1.getField("a"); System.out.println("成员变量a:" + field); /public java.lang.String ewen.Person.a//使用getField()方法获取非public修饰的方法,报NoSuchFieldException/* Field field2 = clazz1.getField("b"); System.out.println("protected修饰的b" + field2);*///获取所有成员变量 Field[] fields2 = clazz1.getDeclaredFields();for (Field field1 : fields2) { System.out.println(field1); //所有成员变量 }//获取指定成员变量,不考虑修饰符 Field field3 = clazz1.getDeclaredField("d"); System.out.println(field3); /public java.lang.String ewen.Person.d
2)获取类的构造方法
//获取构造函数Constructor con = clazz1.getDeclaredConstructor(String.class, int.class);System.out.println(con); //private ewen.Person(java.lang.String,int)
3)获取类中的方法
//获取指定的成员变量 Field field = clazz1.getField("a"); System.out.println("成员变量a:" + field); Person person2 = new Person();//设置值 field.set(person2,"aaa"); System.out.println("a的值:" + person2.getA()); //a的值:aaa
//获取指定的成员变量 Field field = clazz1.getField("a"); System.out.println("成员变量a:" + field); Person person2 = new Person();//获取person2中的a的值 Object value = field.get(person2); System.out.println("a的值:" + value); //a的值为null,String类型的成员变量默认为null。
//获取指定成员变量,不考虑修饰符 Field field3 = clazz1.getDeclaredField("d"); System.out.println(field3);//设置值 Person person1 = new Person();/* 忽略访问权限修饰符的安全检查,d是private修饰的,如果不忽略 访问权限修饰符的安全检查,会报IllegalAccessException异常。 */ field3.setAccessible(true); field3.set(person1,"111"); System.out.println("d的值:" + person1.getD()); //d的值:111
2)Constructor:构造方法对象
/获取构造函数 Constructor con1 = clazz1.getConstructor(String.class);//创建对象 Object person3 = con1.newInstance("张三");
如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance方法。
如果构造函数是private修饰的,也可以调用setAccessible(true)来忽略访问权限的安全检查。
Object person4 = clazz1.newInstance();
3)Method:方法对象
//获取方法对象 Method method = clazz1.getMethod("sleep");//执行方法 method.invoke(person1);
Method 调用 invoke() 的时候,存在许多细节:
invoke() 方法中第一个参数 Object 实质上是 Method 所依附的 Class 对应的类的实例,如果这个方法是一个静态方法,那么 obj 为 null,后面的可变参数 Object 对应的自然就是参数。
invoke() 返回的对象是 Object,所以实际上执行的时候要进行强制转换。
在对Method调用invoke()的时候,如果方法本身会抛出异常,那么这个异常就会经过包装,由Method统一抛InvocationTargetException。而通过InvocationTargetException.getCause() 可以获取真正的异常。
pro.properties文件:pro.className=ewen.Personpro.methodName=sleeppublic class UseReflect {public static void main(String[] args) throws Exception {//加载配置文件/* 创建Properties对象。 Properties是Java中jdk自带的一个对象 我们可以直接将后缀为properties的文件变为Properties对象, 然后通过Porperties对象中的方法对.properties文件对象进行操作 */ Properties pro = new Properties();//获得配置文件(pro.properties)的字节流 InputStream is = UseReflect.class.getClassLoader().getResourceAsStream("pro.properties");//从输入流中读取属性列表(键和元素对)。 pro.load(is);//获取配置文件中定义的数据 String className = pro.getProperty("pro.className"); String methodName = pro.getProperty("pro.methodName");//获取Class对象 Class clazz = Class.forName(className);//获取类对象 Object obj = clazz.newInstance();//获取方法对象 Method method = clazz.getMethod("sleep");//执行方法 method.invoke(obj); }}
只需更改配置文件pro.properties文件就可以,在不改变代码的前提下,执行任意类的任意方法。
反射的优缺点
优点
【END】
更多精彩推荐
☞突发!印度封禁抖音、微信、快手等 59 款中国 App
☞深度学习先驱 Yann LeCun 被骂到封推!AI 偏见真该甩锅数据集?
☞他被称为"中国第一程序员",一人之力单挑微软,如今拜入武当修道
☞高文、张钹、杨强隔空论道:AI精度与隐私的博弈
☞带你从零入门 Serverless | 一文详解 Serverless 架构模式
☞中央银行数字货币的总体框架
欢迎“分享”、“点赞”、“在看”三连走起!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。