欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java反射、泛型、容器

程序员文章站 2022-03-10 17:07:19
Java反射、泛型、容器反射一、什么是反射?二、创建Class对象的三种方式方法一:直接通过一个class的静态变量class获取方法二:通过该实例变量提供的getClass()方法获取方法三:通过静态方法Class.forName()获取三、通过Class创建对象无参构造方法有参构造方法四、通过反射获取属性值五、创建一个反射工具类泛型容器反射一、什么是反射?Class是反射的核心。二、创建Class对象的三种方式创建一个实体类Person:package com.company.demo2;...

反射

一、什么是反射?

Class是反射的核心。
JVM中每个Class实例都指向一个数据类型(class或者interface),而这个实例又包含有class的所有信息。

二、创建Class对象的三种方式

JVM创建的class 的实例Class具有唯一性。

创建一个实体类Person:

package com.company.demo2;

public class Person {

    public String name;

    private Integer age;

    public Person() {
    }

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

方法一:直接通过一个class的静态变量class获取

// 方式一:类.class
Class personClazz = Person.class;

方法二:通过该实例变量提供的getClass()方法获取

// 方式二:示例.getClass()
Person person = new Person();
Class personClazz1 = person.getClass();

方法三:通过静态方法Class.forName()获取

// 方式三:Class.forName("类的全路径")
Class personClazz2 = Class.forName("com.company.demo2.Person");

拓展

因为Class实例在JVM中是唯一的,所以,上述方法获取的Class实例是同一个实例。可以用==比较两个Class实例:

Class cls1 = String.class;
String s = "Hello";
Class cls2 = s.getClass();
boolean sameClass = cls1 == cls2; // true

注意一下Class实例比较和instanceof的差别:

Integer n = new Integer(123);
boolean b1 = n instanceof Integer; // true,因为n是Integer类型
boolean b2 = n instanceof Number; // true,因为n是Number类型的子类
boolean b3 = n.getClass() == Integer.class; // true,因为n.getClass()返回Integer.class
boolean b4 = n.getClass() == Number.class; // false,因为Integer.class!=Number.class

用instanceof不但匹配指定类型,还匹配指定类型的子类。而用双等于判断class实例可以精确地判断数据类型,但不能作子类型比较。
通常情况下,我们应该用instanceof判断数据类型,因为面向抽象编程的时候,我们不关心具体的子类型。只有在需要精确判断一个类型是不是某个个class的时候,我们才使用双等于判断class实例。

三、通过Class创建对象

不考虑反射,正常场景:

Person person = new Person(); // 调用构造方法

考虑反射,同样也是需要靠构造方法来创建对象的。

无参构造方法

public void test2() throws Exception {
    //第一步:获取到Class对象
    Class personClazz = Person.class;

    // 第二步:获取构造方法
    Constructor<Person> constructor = personClazz.getConstructor();

    // 第三步:创建对象
    Person person = constructor.newInstance();

    System.out.println(person);
}

Spring组件即通过反射使用无参构造方法创建bean:

<bean id="person" class="com.company.demo2.Person"></bean>

有参构造方法

public void test3() throws Exception {
   // 第一步:获取到Class对象
   Class personClazz = Person.class;

   // 第二步:获取构造方法
   Constructor<Person> constructor = personClazz.getConstructor(String.class, Integer.class);

   // 第三步:创建对象
   Person person = constructor.newInstance("张三", 10);

   System.out.println(person);
   System.out.println(person.getName() + ":" + person.getAge());
}

Spring组件即通过反射使用有参构造方法创建bean:

<bean id="person" class="com.company.demo2.Person">
 	<constructor-arg index="0" type="java.lang.String" value="张三"></constructor-arg>
	<constructor-arg index="1" type="java.lang.Integer" value="10"></constructor-arg>
</bean>

四、通过反射获取属性值

反射是指将一个类的成员映射成相对应的java类型
成员:

  • 属性Field.java
  • 方法(构造函数Constructor.java、静态方法、普通方法Method.java)
  • 包路径 Package.java
public void test4() throws Exception {
    // 第一步:获取Class对象
    Class personClazz = Person.class;

    // 第二步:获取构造方法
    Constructor<Person> constructor = personClazz.getConstructor(String.class, Integer.class);
    Person person = constructor.newInstance("张三", 10);

    // 第三步:通过Class对象,获取Field对象
    // a.获取public权限的属性
    Field nameField = personClazz.getField("name");
    // b.获取private权限的属性
    Field ageField = personClazz.getDeclaredField("age");
    ageField.setAccessible(true);

    // 第四步:获取属性值
    String name = String.valueOf(nameField.get(person));
    int age = (Integer) ageField.get(person);

    System.out.println(name + ":" + age);
}

详细介绍,推荐网址:https://www.liaoxuefeng.com/wiki/1252599548343744/1264803033837024

五、创建一个反射工具类

public static void convertOf(Object sourceObj, Object targetObj) throws Exception {
    Class sourceClass = sourceObj.getClass();
    Class targetClass = targetObj.getClass();

    Field[] sourceClassDeclaredFields = sourceClass.getDeclaredFields();
    Field[] targetClassDeclaredFields = targetClass.getDeclaredFields();

    for (Field sourceClassDeclaredField : sourceClassDeclaredFields) {
        for (Field targetClassDeclaredField : targetClassDeclaredFields) {
            sourceClassDeclaredField.setAccessible(true);
            targetClassDeclaredField.setAccessible(true);
            if (sourceClassDeclaredField.getName().equals(targetClassDeclaredField.getName())) {
                targetClassDeclaredField.set(targetObj, sourceClassDeclaredField.get(sourceObj));
            }
        }
    }
}
public static void main(String[] args) throws Exception {
    //属性值复制
    Person person = new Person("aaa", 12);
    Person1 person1 = new Person1();
    Main.convertOf(person, person1);
    System.out.println(person1.getName() + ":" + person1.getAge1());
}

补充:

package com.company.demo2;

public class Person1 {

    public String name;

    private Integer age1;

    public Person1() {
    }

    public Person1(String name, Integer age1) {
        this.name = name;
        this.age1 = age1;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge1() {
        return age1;
    }

    public void setAge1(Integer age1) {
        this.age1 = age1;
    }
}

泛型

容器

本文地址:https://blog.csdn.net/qq_33507618/article/details/111992595

相关标签: java 反射