细说Java反射机制

编译期和运行期

在这里插入图片描述
假如我们写了一个Demo.java,并要打印hello world那它需要经过哪些步骤?

第一步:通过编译器进行编译,从Java源码 —> Java 字节码

这个编译器则是jdk 里的javac 编译器,我们只需 javac Demo.java 即可以编译该源码,javac 编译器位于jdk --> bin -->javac

编译器(compiler)是一种计算机程序,它会将某种编程语言写成的源代码(原始语言)转换成另一种编程语言(目标语言)。

第二步:加载java 字节码并执行(load and execute)

可以通过jdk 里的java命令运行java字节码,我们只需 java Demo.class 即可加载并执行该字节码,当运行java命令时,JRE将与你指定的类一起加载。然后,执行该类的主要方法。

上面只是大概讲了运行一个java程序的流程,下面再从编译期以及运行期的角度在剖析一下细节;

1、编译期都做了什么?
在这里插入图片描述

从我们使用者角度看无非就是把源代码编译成了可被虚拟机执行的字节码,但是从平台(编译器)角度看,它所经历的流程还不少。 毕竟总不能给你什么以.java为后缀的文件都进行编译吧,需要有各种校验解析步骤;

在这里插入图片描述
2、运行期间都做了什么?
在这里插入图片描述

Java的运行期主要是处理编译器产生的字节码,包括加载与执行

在这里插入图片描述

Java的类加载

1、Java在真正需要使用一个类时才会去加载类,而不是在启动程序时就载入所有的类,因为大多数使用者都只使用到程序的部分资源,在需要某些功能时再载入某些资源,可以让系统资源运用的更高效。
2、类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在Jvm的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构。类的加载的最终产品是位于堆区中的Class对象,Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口
Java 中的所有类型包括基本类型(int, long, float等等),即使是数组都有与之关联的 Class 类的对象。
3、Class对象是由Jvm自动生成的,每当一个类被载入时,Jvm就自动为其生成一个Class对象

类加载器

1、概述

负责将.class文件加载到内在中,并为之生成对应的Class对象;

2、分类

类加载器名称
Bootstrap ClassLoader根类加载器
Extension ClassLoader扩展类加载器
Sysetm ClassLoader系统类加载器

3、作用

  • Bootstrap ClassLoader 根类加载器

也被称为引导类加载器,负责Java核心类的加载
比如System,String等,在JDK中JRE的lib目录下rt.jar文件中;

  • Extension ClassLoader 扩展类加载器

负责JRE的扩展目录中jar包的加载,在JDK中JRE的lib目录下ext目录;

  • Sysetm ClassLoader 系统类加载器

负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径,比如加载我们自定定义的类 Student.class、Teacher.class;

反射

  • 在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。
  • 用一句话总结就是反射可以实现在运行时知道任意一个类的属性和方法;

反射常用的API

获取类的字节码对象

要使用反射机制,就要先获取一个类的字节码文件对象(class字节码文件类型);

方式1:

通过该类对象的getClass()获取,该方法是Object类的成员方法,所有对象都可以使用;

public class MyTest {
    public static void main(String[] args) throws ClassNotFoundException {
        Student student = new Student();
        Class<? extends Student> aClass = student.getClass();
        System.out.println(aClass);

    }
}
输出:class org.westos.demo2.Student

方式2:

通过Class类里面的forName()获取该类的字节码文件对象,需要的参数是全限定类名,也就是包名+类名,用于明确类的唯一性

public static Class<?> forName(String className) throws ClassNotFoundException
返回与带有给定字符串名的类或接口相关联的 Class 对象;

public class MyTest {
    public static void main(String[] args) throws ClassNotFoundException {
        Class<?> bClass = Class.forName("org.westos.demo2.Student");
        System.out.println(bClass);
        System.out.println(bClass);

    }
}
输出:class org.westos.demo2.Student

方式3:

通过该类的class属性获取该类的字节码文件对象;

public class MyTest {
    public static void main(String[] args) throws ClassNotFoundException {
        Class<Student> sClass = Student.class;
        System.out.println(sClass);
        System.out.println(sClass);

    }
}
输出:class org.westos.demo2.Student

获取构造方法

  • 以前我们获取一个类的对象,必须使用它的构造方法,如果这个构造方法被私有了,我们就无法创建对象;
  • 因为Java里面"万物皆对象",构造方法使用Constructor类来描述;
    在这里插入图片描述
  • 现在可以使用反射的方式获取构造方法对象;
  • 常用方法:

Class类中:
在这里插入图片描述
public Constructor<?>[] getConstructors()
返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法
public Constructor<T> getConstructor(Class<?>... parameterTypes)
返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法,需要参数是构造方法形参数据类型的字节码文件对象
public Constructor<?>[] getDeclaredConstructors()
返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法,需要参数是构造方法形参数据类型的字节码文件对象

Constructor类中:
public T newInstance(Object... initargs)
使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例;
Constructor类的父类 AccessibleObject中:
public void setAccessible(boolean flag)
将此对象的 accessible 标志设置为指示的布尔值;
该方法用于私有构造方法,默认是不取消权限检查,这时候你使用反射创建对象的时候就会失败,我们如果想使用私有构造创建该类的对象,就将取消权限检查设置为true

代码示例1: 使用反射获取公共的构造方法并创建对象

-----自定义类:
public class Student {
    private int age;
    private String name;

    private Student() {

    }

    public Student(String name) {
        this.name = name;
    }

    public Student(int age) {
        this.age = age;
    }

    private Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}
-----测试类:
import java.lang.reflect.Constructor;

public class MyTest1 {
    public static void main(String[] args) throws Exception {
        Class<?> aClass = Class.forName("org.westos.demo2.Student");
        Constructor<?>[] constructors = aClass.getConstructors();
        for (Constructor<?> c : constructors) {
            System.out.println(c);
        }

        /* public org.westos.demo2.Student(int)
        public org.westos.demo2.Student(java.lang.String)
        只获取到两个公共的构造方法 */

        System.out.println("---------------------------");
        Constructor<?> ac = aClass.getConstructor(String.class);
        Object stu1 = ac.newInstance("张三");
        System.out.println(stu1);
        //Student{age=0, name='张三'}

        Constructor<?> bc = aClass.getConstructor(int.class);
        Object stu2 = bc.newInstance(20);
        System.out.println(stu2);
        //Student{age=20, name='null'}
    }
}

代码示例2: 使用反射获取所有的构造方法并创建对象

----Student类和上面一样,这里不再重复
----测试类:
import java.lang.reflect.Constructor;

public class MyTest2 {
    public static void main(String[] args) throws Exception {
        Class<?> aClass = Class.forName("org.westos.demo2.Student");
        Constructor<?>[] constructors = aClass.getDeclaredConstructors();
        for (Constructor<?> c : constructors) {
            System.out.println(c);
        }
        /*private org.westos.demo2.Student(java.lang.String,int)
        public org.westos.demo2.Student(int)
        public org.westos.demo2.Student(java.lang.String)
        private org.westos.demo2.Student()*/

        System.out.println("===========================");

        Constructor<?> ac = aClass.getDeclaredConstructor();
        //取消权限检查
        ac.setAccessible(true);
        Object stu1 = ac.newInstance();
        System.out.println(stu1);
        //Student{age=0, name='null'}

        Constructor<?> bc = aClass.getDeclaredConstructor(String.class);
        Object stu2 = bc.newInstance("张三");
        System.out.println(stu2);
        //Student{age=0, name='张三'}

        Constructor<?> cc = aClass.getDeclaredConstructor(int.class);
        Object stu3 = cc.newInstance(20);
        System.out.println(stu3);
        //Student{age=20, name='null'}

        Constructor<?> dc = aClass.getDeclaredConstructor(String.class, int.class);
        //取消权限检查
        dc.setAccessible(true);
        Object stu4 = dc.newInstance("李四", 21);
        System.out.println(stu4);
        //Student{age=21, name='李四'}
    }
}
  • 总结:使用反射创建一个类的对象步骤

  • 1、获取该类的字节码文件对象

  • 2、获取需要的构造方法对象

  • 3、取消权限检查(如果该构造方法是私有的)

  • 4、通过该构造方法对象创建该类的对象,并根据需求指定所需的参数完成初始化;

  • 如果你只是想要创建空参构造型的对象,可以直接使用字节码文件对象里面的方法创建,但是你必须保证这个空参构造是公有的,要不然他仍然会报出IllegalAccessException错误;

public T newInstance()
创建此 Class 对象所表示的类的一个新实例;

public class MyTest3 {
    public static void main(String[] args) throws Exception{
        Class<?> aClass = Class.forName("org.westos.demo2.Student");
        Object o = aClass.newInstance();
        System.out.println(o);
    }
}

获取成员变量

  • Java中使用Field类来描述成员变量;
    在这里插入图片描述
  • 常用的方法:
方法作用
getFields()返回一个包含公共字段 Field 对象的数组
getField(String name)返回一个名为name的公共字段对象
getDeclaredFields()返回包含所有字段对象的数组
getDeclaredField(String name)返回指定名为name的字段对象
get(Object obj)返回指定对象上此 Field 表示的字段的值
set(Object obj, Object value)设置指定对象的此字段值为指定值
setAccessible(boolean flag)设置权限检查是否取消

代码演示1: 获取所有的字段对象

----自定义类:
public class Dog {
    public String name;
    public int age;
    private char sex;
    private Dog(){}

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sex=" + sex +
                '}';
    }
}
---测试类:
import java.lang.reflect.Field;

public class MyTest5 {
    public static void main(String[] args) throws Exception {
        //1.你要使用反射,第一步先获取该类的字节码文件对象。
        Class<?> aClass = Class.forName("org.westos.demo2.Dog");
        //2.获取Dog类中的所有字段对象,但是私有的字段对象获取不到
        Field[] fields = aClass.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        /*public java.lang.String org.westos.demo2.Dog.name
        public int org.westos.demo2.Dog.age*/
        System.out.println("==================================");

        //获取Dog类中的所有字段对象,包括私有的字段对象
        Field[] fields2 = aClass.getDeclaredFields();
        for (Field field : fields2) {
            System.out.println(field);
        }
        /*public java.lang.String org.westos.demo2.Dog.name
        public int org.westos.demo2.Dog.age
        private char org.westos.demo2.Dog.sex*/
        System.out.println("=============================");

        //获取单个的非私有的字段对象,你要获取哪个字段对象,你名字传入
        Field fieldName = aClass.getField("name");
        System.out.println(fieldName);
        //public java.lang.String org.westos.demo2.Dog.name

        Field fieldAge = aClass.getField("age");
        System.out.println(fieldAge);
        //public int org.westos.demo2.Dog.age

        System.out.println("====================");

        //获取单个的私有字段或非私有字段的对象
        Field fieldSex= aClass.getDeclaredField("sex");
        System.out.println(fieldSex);
        //private char org.westos.demo2.Dog.sex
    }
}

代码演示2: 通过反射的方式获取或者设置对象的字段值

----自定义类与上面一样,不再赘述
----测试类:
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

public class MyTest6 {
    public static void main(String[] args) throws Exception{
        //我们通过反射的方式,给类中的成员变量设置值,以及获取值。

        //1.你要使用反射,第一步先获取该类的字节码文件对象
        Class<?> aClass = Class.forName("org.westos.demo2.Dog");

        //2.给name字段设置,我们就要获取到name字段对象
        Field fieldName = aClass.getField("name");

        //3、通过反射,创建一个类的对象
        Constructor<?> c = aClass.getDeclaredConstructor();
        c.setAccessible(true);
        Object obj = c.newInstance();

        //4、set()方法要两个参数,第一个参数,该类的对象,第二个就是你要设置的具体的值
        fieldName.set(obj,"小黑");

        //获取name字段的值
        Object o = fieldName.get(obj);
        System.out.println(o);
        //小黑

        System.out.println("===================================");

        Field fieldAge = aClass.getField("age");
        fieldAge.setInt(obj,100);

        int anInt = fieldAge.getInt(obj);
        System.out.println(anInt);
        //100

        System.out.println("===================================");

        //给私有字段设置值
        Field fieldSex = aClass.getDeclaredField("sex");
        //5、对于私有的,我们可以取消语法检查
        fieldSex.setAccessible(true);
        fieldSex.setChar(obj,'女');

        //获取
        char aChar = fieldSex.getChar(obj);
        System.out.println(aChar);
        //女

        System.out.println(obj);
        //Dog{name='小黑', age=100, sex=女}
    }
}

获取成员方法

  • Java中使用Method类来描述成员方法;
    在这里插入图片描述
  • 常用的方法:
方法作用
invoke(Object obj, Object… args)对带有指定参数的指定对象调用由此 Method 对象表示的底层方法
getMethods()返回一个包含某些公共的 Method 对象的数组
getMethod(String name, Class<?>… parameterTypes)返回一个公共的,指定方法名的Method 对象
getDeclaredMethods()返回一个包含所有方法对象的数组
getDeclaredMethod(String name,Class<?>… parameterTypes)返回一个指定方法名的Method对象

注意:

1、getMethods()获取所有公有的方法,包括从父类继承下来的;
2、getDeclaredMethods()获取所有的方法,不包括父类的;

代码演示1: 获取所有的方法对象

----自定义类:
public class Student {
    private Student() {
    }

    public void haha(String name) {
        System.out.println(name + "哈哈");
    }

    public void hehe() {
        System.out.println("呵呵");
    }

    public void test(String name, int age) {
        System.out.println(name + "test" + age);
    }

    public String test2(String name, int age) {
        System.out.println(name + "test2" + age);
        return "abc";
    }

    private String show(String name, int age) {
        System.out.println(name + "show" + age);
        return "AAA";
    }
}
----测试类1import java.lang.reflect.Method;
public class MyTest {
    public static void main(String[] args) throws Exception {
        //1.获取该类的字节码文件对象
        Class<?> aClass = Class.forName("org.westos.demo3.Student");
        
        //2.获取类中所有的成员方法对象,获取到非私有的方法对象,包括从父类继承下来的方法对象也能够获取到
        Method[] methods = aClass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }

		/*public void org.westos.demo3.Student.test(java.lang.String,int)
        public void org.westos.demo3.Student.hehe()
        public void org.westos.demo3.Student.haha(java.lang.String)
        public java.lang.String org.westos.demo3.Student.test2(java.lang.String,int)
        public final void java.lang.Object.wait() throws java.lang.InterruptedException
        public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
        public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
        public boolean java.lang.Object.equals(java.lang.Object)
        public java.lang.String java.lang.Object.toString()
        public native int java.lang.Object.hashCode()
        public final native java.lang.Class java.lang.Object.getClass()
        public final native void java.lang.Object.notify()
        public final native void java.lang.Object.notifyAll()*/
}
----测试类2import java.lang.reflect.Method;

public class MyTest {
    public static void main(String[] args) throws Exception {
        //1.获取该类的字节码文件对象
        Class<?> aClass = Class.forName("org.westos.demo3.Student");

        //3、获取所有的方法对象,包括私有的,但是不获取父类的方法对象
        Method[] declaredMethods = aClass.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }
        /*public void org.westos.demo3.Student.test(java.lang.String,int)
        private java.lang.String org.westos.demo3.Student.show(java.lang.String,int)
        public void org.westos.demo3.Student.haha(java.lang.String)
        public void org.westos.demo3.Student.hehe()
        public java.lang.String org.westos.demo3.Student.test2(java.lang.String,int)*/

        System.out.println("==================================");

        //4、获取单个的非私有方法对象
        Method heheMethod = aClass.getMethod("hehe");
        System.out.println(heheMethod);
        //public void org.westos.demo3.Student.hehe()

        System.out.println("==================================");

        //5、获取有参的方法对象 getMethod()方法的参数1:方法名 参数2:方法上形参的数据类型的Class类型
        Method haha = aClass.getMethod("haha", String.class);
        System.out.println(haha);
        //public void org.westos.demo3.Student.haha(java.lang.String)
        System.out.println("==================================");

        Method test = aClass.getMethod("test", String.class, int.class);
        System.out.println(test);
        //public void org.westos.demo3.Student.test(java.lang.String,int)
        System.out.println("==================================");

        //6、获取单个的私有方法对象
        Method show = aClass.getDeclaredMethod("show", String.class, int.class);
        System.out.println(show);
        //private java.lang.String org.westos.demo3.Student.show(java.lang.String,int)
    }
}

代码演示2: 反射执行方法

-----自定义类与上面一样,不再赘述
----测试类:
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class MyTest1 {
    public static void main(String[] args) throws Exception {
        //1、获取该类的字节码文件对象
        Class<?> aClass = Class.forName("org.westos.demo3.Student");

        //2、获取该类的对象
        Constructor<?> constructor = aClass.getDeclaredConstructor();
        constructor.setAccessible(true);
        Object obj = constructor.newInstance();

        //3、获取该类的方法对象
        Method haha = aClass.getDeclaredMethod("haha", String.class);

        //4、执行方法
        haha.invoke(obj, "张三");
        //张三哈哈


        Method hehe = aClass.getDeclaredMethod("hehe");
        hehe.invoke(obj);
        //呵呵

        Method test = aClass.getDeclaredMethod("test", String.class, int.class);
        test.invoke(obj, "李四", 24);
        //李四test24

        Method test2 = aClass.getDeclaredMethod("test2", String.class, int.class);
        Object result1 = test2.invoke(obj, "王五", 25);
        //王五test225
        System.out.println(test2.getName() + "方法的返回值为:" + result1);
        //test2方法的返回值为:abc

        Method show = aClass.getDeclaredMethod("show", String.class, int.class);
        show.setAccessible(true);
        Object result2 = show.invoke(obj, "赵六", 26);
        //赵六show26
        System.out.println(show.getName() + "方法的返回值为:" + result2);
        //show方法的返回值为:AAA
    }
}

反射的优缺点

为什么要用反射机制?直接创建对象不就可以了吗,这就涉及到了动态与静态的概念:

静态编译:在编译时确定类型,绑定对象,即通过;
动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了Java的灵活性,体现了多态的应用,有以降低类之间的藕合性;

优点

  • 可以实现动态创建对象和编译,体现出很大的灵活性。
  • 比如,一个大型的软件,不可能一次就把把它设计的很完美,当这个程序编译后发布,当发现需要更新某些功能时,我们不可能要用户把以前的卸载,再重新安装新的版本,假如这样的话,这个软件肯定是没有多少人用的。
  • 采用静态的话,需要把整个程序重新编译一次才可以实现功能的更新,而采用反射机制的话,它就可以不用卸载,只需要在运行时才动态的创建和编译,就可以实现该功能。

缺点

  • 对性能有影响;
  • 使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求,但是这类操作总是慢于只直接执行相同的操作。

反射的练习

通过反射修改配置文件的内容

需求:刚开始你们老板给的需求是基于狗类开发,那你肯定是new狗类对象,调用里面的eat(),但是过几天,需求改为基于猫类开发,那你肯定是把原来的new狗类对象改为new猫类对象,但是这样显得很麻烦,一直要改代码,这时候我们可以利用反射,我们将使用的类和调用的方法名写入配置文件当中,然后使用反射去加载该类以及调用该类的方法,实现代码之间的 解耦

代码编写:

---狗类:
public class Dog {
    public void eat() {
        System.out.println("狗吃肉");
    }
}
----猫类:
public class Cat {
    public void eat() {
        System.out.println("猫吃鱼");
    }
}
----配置文件:
className=org.westos.demo4.Dog
methodName=eat
----测试类:
import java.io.FileReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Properties;

public class MyTest {
    public static void main(String[] args) throws Exception {
        //使用反射调用方法

        //1、读取配置文件
        Properties properties = new Properties();
        properties.load(new FileReader("MyConfig.properties"));

        //2、获取给定类的字节码文件对象
        Class<?> aClass = Class.forName(properties.getProperty("className"));
        Constructor<?> constructor = aClass.getDeclaredConstructor();

        //取消权限检查
        constructor.setAccessible(true);

        //3、创建该类的对象
        Object obj = aClass.newInstance();

        //4、获取指定方法对象
        Method method = aClass.getDeclaredMethod(properties.getProperty("methodName"));

        //5、执行该方法
        method.setAccessible(true);
        method.invoke(obj);
        //狗吃肉
    }
}

这样的话,只需要修改配置文件,不需要修改代码,就可以基于任何类开发,后面所学习的框架很多地方也是读取配置文件来加载类,调用方法;

通过反射越过泛型检查

需求:之前在学习泛型的时候,说泛型只在编译期有效,运行期间是无效的,我们给定一个集合,如果指定了是String类型,就只能存储String类型的对象,如果是其他类型,编译器会报错,因为反射是在运行时知道任意一个类的属性和方法,所以我们可以使用反射在代码编写的时候给该集合存入其他类型的对象;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;

public class MyTest1 {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        ArrayList<String> list = new ArrayList<>();
        list.add("爱学习,爱Java");
        list.add("爱生活!");
        //list.add(20);报错

        //1、获取ArrayList的字节码文件对象
        Class<? extends ArrayList> aClass = list.getClass();
        //2、获取该类的add(),他需要的参数是一个Object类型,因此我们传递的是Object类的字节码文件对象
        Method method = aClass.getDeclaredMethod("add", Object.class);
        //3、执行该方法
        Object result = method.invoke(list, 20);
        //4、打印返回值
        System.out.println(method.getName() + "方法的返回值为:" + result);
        Object result1 = method.invoke(list, true);
        //add方法的返回值为:true
        System.out.println(method.getName() + "方法的返回值为:" + result1);
        //add方法的返回值为:true

        System.out.println(list);
        //[爱学习,爱Java, 爱生活!, 20, true]
    }
}

写一个通用的设置某个对象的某个属性为指定的值

---测试类:
import java.lang.reflect.Constructor;
public class MyTest {
    public static void main(String[] args) throws Exception {
        //1、获取该类的构造方法对象
        Constructor<?> constructor = Class.forName("org.westos.demo5.Teacher").getDeclaredConstructor();
        constructor.setAccessible(true);
        
        //2、通过反射创建该类的对象
        Object obj = constructor.newInstance();

        //3、设置对象的字段值
        MyUtils.setProperty(obj, "name", "张三");
        //4、获取该对象的字段值
        Object name = MyUtils.getProperty(obj, "name");
        System.out.println(name);
        //张三

        MyUtils.setProperty(obj, "age", 30);
        Object age = MyUtils.getProperty(obj, "age");
        System.out.println((Integer) age);
        //30
    }
}
----工具类:
import java.lang.reflect.Field;
public class MyUtils {

    public static Object getProperty(Object obj, String name) throws Exception {
        //获取该对象所属类的字节码文件对象
        Class<?> aClass = obj.getClass();
        //获取该字段对象
        Field field = aClass.getDeclaredField(name);
        //取消权限检查
        field.setAccessible(true);
        //获取字段值
        Object result = field.get(obj);

        return result;
    }

    public static void setProperty(Object obj, String name, Object value) throws Exception {
        //获取该对象所属类的字节码文件对象
        Class<?> aClass = obj.getClass();
        //获取该字段对象
        Field field = aClass.getDeclaredField(name);
        //取消权限检查
        field.setAccessible(true);
        //设置字段值
        field.set(obj, value);
    }
}
---自定义类:
public class Teacher {
    private int age;
    private String name;
    private Teacher() {
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值