Java 反射

 2023-02-01
原文作者:蒋先森 原文地址:https://jlj98.top/

如果有问题,希望指出

Reflection(反射)是 Java 被视为动态语言的关键,反射机制允许程序在执行期借用 Reflection API 获取任何内部信息,并能操作任何对象的内部属性级方法。

Java 反射机制主要提供一下功能:

  • 在运行时构造任意一个类的对象
  • 在运行时获取任意一个类所具有的成员变量和方法
  • 在运行时调用任意一个对象的方法
  • 生成动态代理

Java 反射提供三种获取 Class 对象的方法:

    Person person = new Person(1L, "反射");
    //1、通过对象名
    Class personClass = person.getClass();
    //2、通过类名
    Class baseClass = Person.class;
    //3、通过全类名
    Class baseClass2 = Class.forName("com.example.basejava.basics.reflect.Person");

Class 是一个类,一个描述类的类。它封装了描述方法的 Method,描述字段的 Filed,描述构造器的 Constructor 等属性。

代码

Person 类

    public class Person implements Serializable {
    
        private Long id;
        private String name;
    
        static {
            System.out.println("测试反射静态代码块");
        }
    
        Person(Person person) {
            System.out.println("(默认)反射测试类构造了" + person);
        }
    
        public Person() {
            System.out.println("调用了公有、无参构造方法执行了。。。");
        }
    
        Person(Long id, String name) {
            this.id = id;
            this.name = name;
        }
    
        Person(String name) {
            this.name = name;
            System.out.println("name+" + name);
        }
    
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "Person{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    '}';
        }
    }

反射具体代码:

    public class ReflectTest {
    
        public static void main(String[] args) throws ClassNotFoundException,
                IntrospectionException,
                IllegalAccessException,
                InvocationTargetException,
                InstantiationException,
                NoSuchMethodException {
            Person person = new Person(1L, "反射");
            //1、通过对象名
            Class clazz1 = person.getClass();
            //2、通过类名
            Class clazz = Person.class;
            //3、通过全类名
            Class clazz2 = Class.forName("com.example.basejava.basics.reflect.Person");
    
            System.out.println("----获取文件名----");
            System.out.println(clazz.getName());
    
            System.out.println("---获取类内部信息-----");
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                //获取内部成员变量,比如 id、name
                String key = field.getName();
                PropertyDescriptor descriptor = new PropertyDescriptor(key, clazz);
                Method method = descriptor.getReadMethod();
                Object value = method.invoke(person);
                System.out.println(key + ":" + value);
            }
    
            System.out.println("----获取实例对象----");
            //利用Class对象的newInstance方法创建一个类的实例
            Object obj = clazz.newInstance();
            System.out.println(obj);
    
            System.out.println("------获取方法---------");
            //获取方法,不能获取private方法,且获取从父类继承来的所有方法
            Method[] methods = clazz.getMethods();
            for (Method method : methods) {
                System.out.print(" " + method.getName());
            }
            System.out.println();
    
            //获取所有方法,包括私有方法
            methods = clazz.getDeclaredMethods();
            for (Method method : methods) {
                System.out.println(" " + method.getName());
            }
            System.out.println();
    
            //获取指定方法
            Method method = clazz.getDeclaredMethod("setName", String.class);
            System.out.println(method);
    
            //修改类内部信息,setName("反射)
            method.invoke(obj, "反射");
            System.out.println(obj);
    
            System.out.println("----所有公有构造方法-----");
            Constructor[] constructors = clazz.getConstructors();
            for (Constructor constructor : constructors) {
                System.out.println(constructor);
            }
    
            System.out.println("-----所有的构造方法(包括:私有、受保护、默认、公有)-------");
            constructors = clazz.getDeclaredConstructors();
            for (Constructor constructor : constructors) {
                System.out.println(constructor);
            }
    
            System.out.println("--------获取公有、无参的构造方法--------");
            Constructor constructor = clazz.getConstructor(null);
            System.out.println("constructor : " + constructor);
    
            System.out.println("------获取私有构造方法,并调用-------");
            Object object = constructor.newInstance();
            constructor = clazz.getDeclaredConstructor(String.class);
            System.out.println(constructor);
            //调用构造方法
            constructor.setAccessible(true);
            object = constructor.newInstance("男");
            System.out.println(object);
        }
    }

输出:

    测试反射静态代码块
    ----获取文件名----
    com.example.basejava.basics.reflect.Person
    ---获取类内部信息-----
    id:1
    name:反射
    ----获取实例对象----
    调用了公有、无参构造方法执行了。。。
    Person{id=null, name='null'}
    ------获取方法---------
     toString getName setName getId setId wait wait wait equals hashCode getClass notify notifyAll
     toString
     getName
     setName
     getId
     setId
    
    public void com.example.basejava.basics.reflect.Person.setName(java.lang.String)
    Person{id=null, name='反射'}
    ----所有公有构造方法-----
    public com.example.basejava.basics.reflect.Person()
    -----所有的构造方法(包括:私有、受保护、默认、公有)-------
    com.example.basejava.basics.reflect.Person(java.lang.String)
    com.example.basejava.basics.reflect.Person(java.lang.Long,java.lang.String)
    public com.example.basejava.basics.reflect.Person()
    com.example.basejava.basics.reflect.Person(com.example.basejava.basics.reflect.Person)
    --------获取公有、无参的构造方法--------
    constructor : public com.example.basejava.basics.reflect.Person()
    ------获取私有构造方法,并调用-------
    调用了公有、无参构造方法执行了。。。
    com.example.basejava.basics.reflect.Person(java.lang.String)
    name+男
    Person{id=null, name='男'}