Java反射
什么是反射
Java 反射是一种机制,允许在运行时检查、获取和操作类、接口、字段、方法等的信息。通过反射,你可以在编译时不知道类的具体信息的情况下,动态地获取并操作类的成员。Java 反射提供了一组类和接口,使得可以在运行时获取类的元数据,调用类的方法,访问类的字段,甚至创建新的类实例。
简单来说,就是在对象生成后,还能通过反射机制来获取对象的信息,操作对象的各种属性,修改属性值,调用方法等
反射机制相关的包
1 | java.lang.reflect.*; |
反射机制相关类
类名 | 含义及作用 |
---|---|
java.lang.Class | 代表整个字节码。代表一个类型,代表整个类。用来获取反射的类 |
java.lang.reflect.Constructor | 代表字节码中的构造方法字节码。用来获取类中的构造方法。 |
java.lang.reflect.Field | 代表字节码中的属性字节码。用来类中的成员变量(静态变量+实例变量),不包括方法。 |
java.lang.reflect.Method | 代表字节码中的方法字节码。代表类中的方法。 |
获取Class字节码的三种方式
要对一个类进行操作,得先能够获取它的类字节码。
方式 | 例子 |
---|---|
Class.forName(“完整类名带包名”) | Class.forname(“com.sec.reflection.Person”) |
对象.getClass() | person.getClass() |
任何类型.class | String.class |
接着用Person类进行说明
1 | package com.security; |
实例化反射对象
获取了类的字节码后,对类进行实例化。
1 | Person person=new Persion(); |
如果要调用有参数的构造方法,就需要使用到Constructor
.
1 | //通过getConstructor()方法构造出构造器,构造器的参数为构造函数的参数对应的字节类 |
执行结果如下:
1 | Person{name=Dragonkeep,age=22} |
获取反射对象的属性
利用Class
类中的getField()
方法来获取反射对象中属性的值。getFields()
方法会返回所有公共属性的类型的成员变量数组,同样也是Field
类。
1 | Field PersonField=c.getField("name"); |
输出结果为Dragonkeep
如果是要获取私用属性的值的话,需要使用getDecleardField()
方法。
例如上面例子中的age
属性,
1 | Field PersonField =c.getDeclaredField("age"); |
输出结果为22
当然不仅可以get
也可以使用set
方法
1 | Field PersonField=c.getDeclaredField("name"); |
获取反射对象的方法
利用Class类
中的getMethod(String name,Class<?>... parameterTypes)
方法来获取方法.,在配合Method
类中的invoke(Object obj, Object... args)
进行调用方法。
getMethod:
- name:为方法名
- parameterTypes:为方法参数对应的字节码类
invoke:
- obj:为反射对象
- args:方法对应的实参
下面举例说明:
1 | Method method =c.getMethod("action1"); //调用无参方法 |
输出结果为:
1 | action1 with nothing |
如果是获取私有属性的方法,就使用getDeclaredMethod
.
使用技巧同上getDecleardField()
方法
1 | Method method3=c.getDeclaredMethod("action3", String.class); |
输出:
1 | action3 with Don`t sad |
总结:
使用getDecleard()*
的方法能访问私有属性和公有,相比get*()
方法好用。
Java利用反射执行本地命令代码
反射Runtime类
执行本地命令代码,Runtime类位于java.lang.Runtime
包中。
1 | //获取Runtime类对象 |
在java9+
后的版本, Java 模块系统不允许通过反射访问 java.lang
包中的私有构造函数
会报java.lang.reflect.InaccessibleObjectException
错误。
另外一种命令执行方法
除了Runtime
类之外,还有一个类可以用来执行命令ProcessBuilder
。同样,我们使用反射来获取构造函数,然后调用start()
函数来执行命令。
1 | Class clazz = Class.forName("java.lang.ProcessBuilder"); |
实测在java17环境下,使用反射调用Runtime类执行命令报错,使用ProcessBuilder
成功执行。
参考学习:
Java反射(超详细!)_一个快乐的野指针~的博客-CSDN博客
本文仅供学习记录,不足之处请指出,谢谢。