Java反射

一、如何获取一个类:

1、Class cls = Class.forName("java.lang.String");

2、String str = "zhangsan";
   Class cls = str.getClass();

3、Class cls = String.class;  //注意String.class的class是小写的C

二、利用反射访问类中的字段:

1、getFields()方法:
获得某个类中所有的公有属性(public)的字段,包括这个类的父类中的public属性字段。

2、getDeclaredFields()方法:
获得某个类中所有属性的字段(public、private、protect),但是不包括这个类的父类。

代码演示:

现有一个 PersonalInfo类 和一个 StuInfo类,StuInfo类继承PersonalInfo类并重写了 toString()方法:

class PersonInfo{
    public String name = "zhangsan";
}

class StuInfo extends PersonInfo{
    public int age;
    private int money;

    @Override
    public String toString() {
        return "StuInfo{" +
                "name=" + name +
                ", money=" + money +
                '}';
    }
}

(1) 使用 getFields()方法获取 类StuInfo中的公有成员变量age和其父类中的公有成员变量name:

Class stiClass = StuInfo.clas;
// 获取public字段"age":
System.out.println(stiClass.getField("age"));
// 获取继承的public字段"name":
System.out.println(stiClass.getField("name"));

(2) 使用 getDeclared()方法获取 类StuInfo中的私有成员变量money:

Class stiClass = StuInfo.class;
System.out.println(stiClass.getDeclaredField("money"));

(3) 使用 newInstance()方法,利用反射创建实例化对象:

Field name = stiClass.getField("name");
System.out.println(name.get(stiClass.newInstance()));

(4) 利用setAccessible()方法设置私有属性money的值:

Field money = stiClass.getDeclaredField("money");
money.setAccessible(true);
money.set(stuInfo,2333333);

//Java 的 setAccessible 是一个访问控制方法,它可以用来控制 Java 中类的访问权限。如果某个成员变量被声明为 private 或 protected,普通的程序是不能访问它的。但是如果使用 setAccessible 方法将其设置为 true,程序就可以访问该变量了。

三、利用反射获取类中的方法:

1、Method getMethod(name, 参数类型):获取当前类中的某个public方法,包括其父类中的方法。

2、Method getDeclaredMethod(name, 参数类型):获取某个类中的某个任意属性的方法(public、private、protect),但不包括其父类中的方法。

3、Method[] getMethods():获取当前类中的所有public方法。

4、Method[] getDeclaredMethods():获取当前类中任意属性的所有方法,但不包括其父类中的方法。

代码演示:

public class reflectTest01 {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        String name = "zhangsan";
        Method substring = String.class.getMethod("substring", int.class);
        System.out.println(substring.invoke(name, 3));
    }
}

//输出结果为 ngsan

Obj参数为null,代码如下:

Method m = Integer.class.getMethod("parseInt", String.class);
System.out.println(m.invoke(null, "3"));

//输出结果为 3

四、获取构造方法:

1、getConstructor(构造方法的参数类型1、构造方法的参数类型2、...):获取当前类中某个public属性的构造方法。

2、getDeclaredConstructor(构造方法的参数类型1、构造方法的参数类型2、...):获取当前类中某个任意属性的构造方法。

3、getConstructors(): 获取当前类中所有public属性的无参数构造方法。

4、getDeclaredConstructors():获取当前类中所有任意属性的无参数构造方法。

注:调用非public属性的构造方法时,必须要先通过 setAccessible(true)设置允许访问,setAccessible(true)可能会失败。

五、java反射进行命令执行:

java语句进行命令执行:

Windows:java.lang.Runtime.getRuntime().exec("cmd /c start calc");

MacOS:java.lang.Runtime.getRuntime().exec("open -na Calculator");

java反射语句进行命令执行:

Windows:
Class.forName("java.lang.Runtime").getMethod("getRuntime").invoke(null)
                .getClass().getMethod("exec", String.class).invoke(Runtime.getRuntime(),"cmd /c start calc");

MacOS:
Class.forName("java.lang.Runtime").getMethod("getRuntime").invoke(null)
                .getClass().getMethod("exec", String.class).invoke(Runtime.getRuntime(),"open -na Calculator");

六、修改被final关键字修饰的变量:

在 javaReflection.User 中,设有 final修饰的整数变量 finalNumber = 666:
image

通过下文代码即可进行修改并打印:

public class reflectTest01 {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, IOException, ClassNotFoundException, InstantiationException, NoSuchFieldException {
        Class userClass = Class.forName("javaReflection.User");
        User user = (User)userClass.newInstance();
        Field field = userClass.getDeclaredField("finalNumber");
        field.setAccessible(true);
        field.setInt(user, 100);
        System.out.println(field.get(user));
    }
}

//输出结果:
//无参数构造方法执行
//100
posted @ 2024-09-24 17:12  OneCoffee  阅读(4)  评论(0编辑  收藏  举报