Java反射、泛型、容器
程序员文章站
2022-03-10 17:07:19
Java反射、泛型、容器反射一、什么是反射?二、创建Class对象的三种方式方法一:直接通过一个class的静态变量class获取方法二:通过该实例变量提供的getClass()方法获取方法三:通过静态方法Class.forName()获取三、通过Class创建对象无参构造方法有参构造方法四、通过反射获取属性值五、创建一个反射工具类泛型容器反射一、什么是反射?Class是反射的核心。二、创建Class对象的三种方式创建一个实体类Person:package com.company.demo2;...
Java反射、泛型、容器
反射
一、什么是反射?
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
上一篇: 【链表】18题-删除链表中重复的节点
下一篇: Java中的泛型