概念
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制
简单实例
获取类对象
package test;
import java.lang.Class.*;
public class reflection1 {
public static void main(String[] args) throws Exception {
Class.forName("test.xxx");
}
}
class xxx{
public void xxx(){
System.out.println("hello world");
}
static {
System.out.println("test1");
}
{
System.out.println("test2");
}
}
- 当
forName
方法获取一个类的时候会调用这个类的static静态代码。
获取类方法
获取全部方法
getMethod
来获取函数的方法,执行invoke
后通过newInstance
来调用构造函数,但是{}
的优先级会比构造方法高,所以运行结果会是先{}
、构造方法、普通方法。
package test;
public class reflection1 {
public static void main(String[] args) throws Exception {
Class clazz=Class.forName("test.xxx");
//实例化类,然后调用方法
clazz.getMethod("hello").invoke(clazz.newInstance());
}
}
class xxx{
public xxx(){
System.out.println("test1");
}
public void hello(){
System.out.println("hello");
}
static {
System.out.println("test2");
}
{
System.out.println("test3");
}
}
- 运行结果
获取无参数构造方法
- 同样先需要获取到对应的类对象,然后通过
getDeclaredConstructor
方法来获取构造方法,这里有个细节如果获取的构造方法是私有(private)时候需要使用setAccessible
,最后使用newInstance
来创建实例。
package test;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class reflection1 {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, ClassNotFoundException {
Class<?> clazz = Class.forName("test.zzz");
Constructor<?> constructor = clazz.getDeclaredConstructor();
constructor.setAccessible(true);
constructor.newInstance();
}
}
class zzz{
private zzz(){
System.out.println("this is zzz");
}
private zzz(String name){
System.out.println("this is "+name);
}
private zzz(int age,String name){
System.out.println("this is "+age+":"+name);
}
}
获取含参数构造方法
- 同样使用
getDeclaredConstructor
方法来获取,但是需要指定参数数据类型。然后在newInstance
传参即可。
package test;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class reflection1 {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, ClassNotFoundException {
Class<?> clazz = Class.forName("test.zzz");
Constructor<?> constructor = clazz.getDeclaredConstructor(String.class);
constructor.setAccessible(true);
constructor.newInstance("黄莉荃");
}
}
class zzz{
private zzz(){
System.out.println("this is zzz");
}
private zzz(String name){
System.out.println("this is "+name);
}
private zzz(int age,String name){
System.out.println("this is "+age+":"+name);
}
}
getDeclaredConstructors
getDeclaredConstructors
将会返回所有构造方法的数组
- 以获取索引为2的方法为例:
package test;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class reflection1 {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, ClassNotFoundException {
Class<?> clazz = Class.forName("test.zzz");
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
Constructor constructor = constructors[2];
constructor.setAccessible(true);
// 输出内容
System.out.println(constructor);
constructor.newInstance(18,"黄莉荃");
}
}
class zzz{
private zzz(){
System.out.println("this is zzz");
}
private zzz(String name){
System.out.println("this is "+name);
}
private zzz(int age,String name){
System.out.println("this is "+age+":"+name);
}
}
获取字段
- 通过
getDeclaredField
来获取字段,如果是私有字段只需加上field.setAccessible(true);
即可
package test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class reflection1 {
public static <Feild> void main(String[] args) throws Exception {
//获取类
Class clazz=Class.forName("test.test");
//获取私有方法
Constructor c = clazz.getDeclaredConstructor();
//获取私有字段
Field field = clazz.getDeclaredField("age");
System.out.println(field.get(c.newInstance()));
}
}
class test{
public test(){
System.out.println("test");
}
public int age=222;
}
修改字段值
- 使用set方法即可修改
package test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class reflection1 {
public static <Feild> void main(String[] args) throws Exception {
//获取类
Class clazz=Class.forName("test.test");
//获取私有方法
Constructor c = clazz.getDeclaredConstructor();
//获取私有字段
Object o = c.newInstance();
Field field = clazz.getDeclaredField("age");
field.set(o,1111);
System.out.println(field.get(o));
}
}
class test{
public test(){
System.out.println("test");
}
public int age=222;
}
反射调用java.lang.Runtime
利用方法一
package test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class reflection1 {
public static <Feild> void main(String[] args) throws Exception {
Class clazz = Class.forName("java.lang.Runtime");
Constructor c = clazz.getDeclaredConstructor();
c.setAccessible(true);
clazz.getMethod("exec", String.class).invoke(c.newInstance(),"open /Users/gqleung/Desktop/aaaa.txt");
}
}
- 成功打开桌面的
aaaa.txt
利用方法二
package test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class reflection1 {
public static <Feild> void main(String[] args) throws Exception {
Class clazz=Class.forName("java.lang.Runtime");
clazz.getMethod("exec", String.class).invoke(clazz.getMethod("getRuntime").invoke(clazz),"ping y3qge8.dnslog.cn");
}
}