Java:反射

反射的定义

java 反射机制是在运行状态中,对于任意一个类、任意一个对象,都能知道和调用它的任意方法和属性,这种动态获取信息以及动态调用对象方法的功能成为Java 的反射机制

获取class 对象

【1】Class.forName(“全类名”):将字节码文件加载进内存,返回Class对象(多用于配置文件)
【2】类名.class:通过类名的属性class获取(多用于参数的传递)
【3】对象.getClass():多用于对象的获取字节码方式

同一个字节码文件(*.class)在一次程序的执行过程中,只会被加载一次,无论通过上述哪种方式获取的Class对象!

/**
 * 获取类的方式:
 *      Class.forName
 *      类名.class
 *      对象.getClass
 */
public static void getClassTest() throws ClassNotFoundException {
    Class cls1 = Class.forName("com.zjh.pojo.Person");
    Class cls2 = Person.class;
    Person p = new Person();
    Class cls3 = p.getClass();

    System.out.println("cls1:" + cls1 + "\ncls2:" + cls2 + "\ncls3:" + cls3);

    System.out.println(cls1 == cls2);//true
    System.out.println(cls1 == cls3);//true
    //同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。
}

Class 对象功能

获取成员变量

  • Field[] getFields()
  • Field getField(String name)
  • Field[] getDeclaredFields()
  • Field getDeclaredField(String name)
    /**
     * 成员变量测试
     */
    public static void fieldTest() throws Exception {

        Class cls1 = Class.forName("com.zjh.pojo.Person");
        //1.Field[] getFields() 获取所有public修饰的成员变量
        Field[] fields = cls1.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        //2.通过成员变量名称获取public修饰的成员变量
        Field a = cls1.getField("a");
        //3.获取成员变量的值
        Person p = new Person();
        System.out.println(a.get(p));
        //4.设置a的值
        a.set(p, "aa");
        System.out.println(p.a);

        //Field[] getDeclaredFields() 获取任意修饰符的成员变量
        Field[] declaredFields = cls1.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
        //通过成员变量获取任意修饰符的成员变量
        Field fieldName = cls1.getDeclaredField("name");
        //忽略访问权限修饰符的安全检查:暴力反射
        fieldName.setAccessible(true);
        //获取p对象下的name属性值
        System.out.println(fieldName.get(p));因为该属性是私有的,所以抛了以下异常:Exception in thread "main" java.lang.IllegalAccessException: Class com.zjh.test.ReflectDemo can not access a member of class com.zjh.pojo.Person with modifiers "private"
        //设置p对象下的name属性值
        fieldName.set(p, "法外狂徒张三");//因为该属性是私有的,所以抛了以下异常:Exception in thread "main" java.lang.IllegalAccessException: Class com.zjh.test.ReflectDemo can not access a member of class com.zjh.pojo.Person with modifiers "private"
        System.out.println(p);
    }

获取构造方法

  • Constructor<?>[] getConstructors()
  • Constructor getConstructor(类<?>… parameterTypes)
  • Constructor getDeclaredConstructor(类<?>… parameterTypes)
  • Constructor<?>[] getDeclaredConstructors()
    public static void constructorTest() throws Exception {
        Class cls1 = Person.class;
        //获取public 修饰的构造方法
        Constructor[] constructors = cls1.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
        //获取public修饰的构造方法
        Constructor constructor = cls1.getConstructor(String.class, int.class);
        //根据构造方法创建对象
        Object instance = constructor.newInstance("法外狂徒张三", 18);
        System.out.println(instance);

        //获取任意修饰符的构造方法
        Constructor[] declaredConstructors = cls1.getDeclaredConstructors();
        for (Constructor declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }

        //获取任意修饰符的构造方法
        Constructor constructor1 = cls1.getDeclaredConstructor(String.class);
        //暴力破解
        constructor1.setAccessible(true);
        Object instance1 = constructor1.newInstance("张三弟弟");//因为该构造方法是私有的,所以抛了以下异常Exception in thread "main" java.lang.IllegalAccessException: Class com.zjh.test.ReflectDemo can not access a member of class com.zjh.pojo.Person with modifiers "private"
        System.out.println(instance1);
    }

获取成员方法

  • Method[] getMethods()
  • Method getMethod(String name, Class<?>… parameterTypes)
  • Method[] getDeclaredMethods()
  • Method getDeclaredMethod(String name, Class<?>… parameterTypes)
    /**
     * 成员方法测试
     *
     * @throws Exception
     */
    public static void methodTest() throws Exception {
        Class cls1 = Person.class;
        //获取方法
        Method[] methods = cls1.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }

        //获取方法
        Method play = cls1.getMethod("play");
        Method study = cls1.getMethod("study", String.class);
        //执行方法
        Person person = new Person();
        play.invoke(person);
        study.invoke(person, "java");

        //获取私有方法
        //cls1.getDeclaredMethods();
        Method playPrivate = cls1.getDeclaredMethod("playPrivate");
        playPrivate.setAccessible(true);//暴力破解
        playPrivate.invoke(person);//Exception in thread "main" java.lang.IllegalAccessException: Class com.zjh.test.ReflectDemo can not access a member of class com.zjh.pojo.Person with modifiers "private"
    }

获取类名name

  • String getName()

整合测试demo

    /**
     * 整合测试
     * 在不修改代码的情况下,可以创建任意类,并执行相应的方法
     */
    public static void reflectTest() throws Exception {

        //通过配置文件读取数据
        //1.创建properties对象
        Properties properties = new Properties();
        //2.加载配置文件
        //2.1获取class目录下的配置文件
        ClassLoader classLoader = ReflectDemo.class.getClassLoader();
        properties.load(classLoader.getResourceAsStream("pro.properties"));
        //3.获取类路径即方法名
        String className = properties.getProperty("reflect.class.name", "com.zjh.pojo.Person");
        String methodName = properties.getProperty("reflect.method", "playPrivate");

        //4.加载该类进内存
        Class<?> cls1 = Class.forName(className);
        //5.创建对象
        Object instance = cls1.newInstance();
        //6.获取方法并执行
        Method method = cls1.getDeclaredMethod(methodName);
        method.setAccessible(true);//暴力反射
        method.invoke(instance);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值