天天看点

一文读懂JAVA反射机制

1. 什么是反射?

java 的反射就是在运行的状态下利用Class文件获取实例的方式,并且获取实例的对象的类的方法、类名、包名、属性等。

Class文件:

  • 类名
  • 方法(构造方法、静态方法、普通方法)Methed
  • 包名 Package
  • 属性(字段 )Field

2. 创建Class对象的几种方式

三种方式

//方式一 类.class
Class personClass1 = Person.class;
//方式二 实例.getClass()
Person person = new Person();
Class personClass2 = person.getClass();
//方式三 Class.forName(”类的全路径“)
Class personClass3 = Class.forName("com.bai.Person");
           

3. 通过Class创建对象

  • 正常情况创建对象获取实例的方式-->构造函数:Person person = new Person();
  • 反射也是通过构造函数来获取对象实例的,Constructor对象。
/**
 * spring 构造 bean
 * 无参
 * <bean id="person" class="com.bai.Person"></bean>
 * 有参
 * <bean id="person" class="com.bai.Person">
 *     <constructor-arg index="0" type="java.lang.String" value="bailiang"/>
 * </bean>
 *
 */
Class personClass2 = Person.class;
//第二步 获取构造函数
//无参
Constructor<Person> constructor = personClass2.getConstructor();
//有参
Constructor<Person> yesConstructor = personClass2.getConstructor(
        String.class, Integer.class, Byte.class, Boolean.class);
//第三步 创建对象
//有参
Person person2 = yesConstructor.newInstance("bailiang", 
    26, (byte) 1, Boolean.FALSE);
System.out.println(JSON.toJSONString(person2));
//无参
Person person = constructor.newInstance();
person.setName("bailiang");
person.setAge(1);
System.out.println(JSON.toJSONString(person));
           

4. 通过反射获取属性值

  • 类的成员包括:属性(Field.java)、方法(构造方法Constructor.java、静态方法、普通方法Methed.java)、包路径(Package.java)。
  • 反射是将类的成员映射成对应的java类型。
@Test
public void test3() throws Throwable {
    //第一步 获取Class对象
    Class personClass2 = Person.class;
    //第二步 获取构造函数
    //无参
    Constructor<Person> constructor = personClass2.getConstructor();
    Person person = constructor.newInstance();
    //第三步 获取public属性 Field
    Field name = personClass2.getField("name");
    System.out.println("public:属性【name】:"+ JSON.toJSONString(name));
    System.out.println(name);
​
    //private 属性
    Field sex = personClass2.getDeclaredField("sex");
    sex.setAccessible(Boolean.TRUE);
    System.out.println(sex.get(person));
    System.out.println("private:属性【sex】:"+person.getSex());
}
           

5. 创建一个反射工具类

利用反射实现一个类的复制的工具类,可以将一个类对象相同的属性复制给另一个对象。

public class BeanUtil {
​
    public static void convertor(Object originObj, Object targetObj) throws IllegalAccessException {
        //第一步 获取Class 对象
        Class<?> originClass = originObj.getClass();
        Class<?> targetClass = targetObj.getClass();
        // 第二步 获取所有属性
        Field[] originDeclaredFields = originClass.getDeclaredFields();
        Field[] targetDeclaredFields = targetClass.getDeclaredFields();
        //第三步 赋值
        for (Field targetDeclaredField : targetDeclaredFields) {
            for (Field originDeclaredField : originDeclaredFields) {
                if (originDeclaredField.getName().equals(targetDeclaredField.getName())) {
                    originDeclaredField.setAccessible(true);
                    targetDeclaredField.setAccessible(true);
                    targetDeclaredField.set(targetObj, originDeclaredField.get(originObj));
                }
            }
        }
    }
​
    public static void main(String[] args) throws IllegalAccessException {
        Person person = new Person();
        CopyPerson copyPerson = new CopyPerson();
        BeanUtil.convertor(person, copyPerson);
        System.out.println(JSON.toJSONString(copyPerson));
    }
}