【Java学习笔记】67:通过反射获取构造器以创建对象,越过权限检查使用成员

版权声明:本文为博主原创学习笔记,如需转载请注明来源。 https://blog.csdn.net/SHU15121856/article/details/79947238

获得类的构造器

通过反射获得类的Class对象,然后就要获得其构造器,才能去创建对象。

package testReflect;

import java.lang.reflect.Constructor;

//自定的一个类
class MyClass {
    private int a1;// 私有成员1
    private double a2;// 私有成员2

    // 默认权限的构造器
    MyClass(int b) {
        this.a1 = b;
    }

    // public权限的无参构造器
    public MyClass() {

    }

    // public权限的有参构造器
    public MyClass(double b) {
        this.a2 = b;
    }

    // private权限的有参构造器
    private MyClass(int b1, double b2) {
        this.a1 = b1;
        this.a2 = b2;
    }

}

// 在主类main方法中测试
public class Main {

    public static void main(String[] args) {
        try {
            // 加载类
            Class cls = Class.forName("testReflect.MyClass");
            // 获取所有public权限的构造器
            Constructor[] ary_con1 = cls.getConstructors();
            System.out.println("所有public权限的构造器:");
            for (Constructor c : ary_con1) {
                System.out.println(c);
            }
            // 获取所有的构造器
            Constructor[] ary_con2 = cls.getDeclaredConstructors();
            System.out.println("所有的构造器:");
            for (Constructor c : ary_con2) {
                System.out.println(c);
            }
            // 获取指定的public构造器,传入的是参数表所在的类的Class对象表
            Constructor con3 = cls.getConstructor(double.class);
            System.out.println("指定的public构造器:");
            System.out.println(con3);
            // 获取指定的构造器,传入的是参数表所在的类的Class对象表
            Constructor con4 = cls.getDeclaredConstructor(int.class,
                    double.class);
            System.out.println("指定的构造器:");
            System.out.println(con4);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }
    }
}

输出:

所有public权限的构造器:
public testReflect.MyClass(double)
public testReflect.MyClass()
所有的构造器:
private testReflect.MyClass(int,double)
public testReflect.MyClass(double)
public testReflect.MyClass()
testReflect.MyClass(int)
指定的public构造器:
public testReflect.MyClass(double)
指定的构造器:
private testReflect.MyClass(int,double)

创建类的对象并使用成员

在使用构造器和使用成员时都可以通过.setAccessible(true)解除限定来越过权限检查。

package testReflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

//自定的一个类
class MyClass {
    private int a1;// 私有成员1
    private double a2;// 私有成员2

    // private权限的有参构造器
    private MyClass(int b1, double b2) {
        this.a1 = b1;
        this.a2 = b2;
        System.out.println("private构造器被调用了");
    }

    // private权限的成员方法
    private String setNum(int b1, double b2) {
        this.a1 = b1;
        this.a2 = b2;
        System.out.println("private成员方法被调用了");
        return "返回值";
    }

}

// 在主类main方法中测试
public class Main {

    public static void main(String[] args) {
        try {
            // 加载类
            Class cls = Class.forName("testReflect.MyClass");

            // 获取指定的构造器,传入的是参数表所在的类的Class对象表
            Constructor con = cls.getDeclaredConstructor(int.class,
                    double.class);
            // 暴力反射,让这个私有构造器对象可以越过权限检查
            con.setAccessible(true);
            // 使用这个构造器创建对象,传入参数
            Object obj = con.newInstance(2, 3.14);

            // 从Class对象获取指定的成员方法
            Method mthd = cls.getDeclaredMethod("setNum", int.class,
                    double.class);
            // 暴力反射,让这个私有成员方法对象可以越过权限检查
            mthd.setAccessible(true);
            // 调用该成员方法,于刚才创建的对象上,还需传入参数
            Object rslt = mthd.invoke(obj, 9, 6.66);
            System.out.println("返回值是:" + rslt.toString());

            // 从Class对象获取指定的成员
            Field f1 = cls.getDeclaredField("a1");
            Field f2 = cls.getDeclaredField("a2");
            // 暴力反射,让这两个私有成员变量可以越过权限检查
            f1.setAccessible(true);
            f2.setAccessible(true);
            // 为第二个成员变量设置值,于刚才创建的对象上,还需传入值
            f2.set(obj, 8.88);
            // 输出这两个字段的值,于刚才创建的对象上
            System.out.println("a1=" + f1.get(obj) + ",a2=" + f2.get(obj));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }
}

输出:

private构造器被调用了
private成员方法被调用了
返回值是:返回值
a1=9,a2=8.88
阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页