Java基础知识6-反射

反射机制概述

是一套类库

  1. 反射机制是JDK中的一套类库,这套类库可以帮助我们操作/读取 class 字节码文件

  2. 后期学习的大量的java框架,底层都是基于反射机制实现的,所以必须掌握(要能够数量的使用反射机制中的方法)。

  3. 反射机制可以让程序更加灵活。怎么灵活????

  4. 反射机制最核心的几个类:

1
2
3
4
java.lang.Class:Class类型的实例代表硬盘上的某个class文件。或者说代表某一种类型。
java.lang.reflect.Filed:Filed类型的实例代表类中的属性/字段
java.lang.reflect.Constructor: Constructor类型的实例代表类中的构造方法
java.lang.reflect.Method: Method类型的实例代表类中的方法

反射机制的缺点:容易打破封装

获取Class

  1. 在java语言中获取Class的三种方式:

==某种类型的字节码文件在内存当中只有一份==

1
2
3
4
5
6
7
8
9
10
11
12
13
// 获取 User 类型
Class userClass = Class.forName("com.powernode.javase.reflect.User");

String s1 = "动力节点";
Class stringClass2 = s1.getClass();

// 某种类型的字节码文件在内存当中只有一份。
// stringClass 和 stringClass2 都代表了同一种类型:String类型
System.out.println(stringClass == stringClass2); // true

User user = new User("zhangsan", 20);
Class userClass2 = user.getClass();
System.out.println(userClass2 == userClass); // true

第一种方式:Class c = Class.forName(“完整的全限定类名”);

注意:

  • 1.全限定类名是带有包名的。
  • 2.是lang包下的,java.lang也不能省略。
  • 3.这是个字符串参数。
  • 4.如果这个类根本不存在,运行时会报异常:java.lang.ClassNotFoundException
  • 5.这个方法的执行会导致类的加载动作的发生。、
1
2
3
4
5
6
// stringClass 就代表 String类型。
// stringClass 就代表硬盘上的 String.class文件。
Class stringClass = Class.forName("java.lang.String");

// 获取 User 类型
Class userClass = Class.forName("com.powernode.javase.reflect.User");

第二种方式:Class c = obj.getClass();

注意:这个方法是通过引用去调用的。

1
2
3
4
5
6
7
String s1 = "动力节点";
Class stringClass2 = s1.getClass();

// 某种类型的字节码文件在内存当中只有一份。
// stringClass 和 stringClass2 都代表了同一种类型:String类型
System.out.println(stringClass == stringClass2); // true

第三种方式:在java语言中,任何一种类型,包括基本数据类型,都有 .class 属性。用这个属性可以获取Class实例。

1
2
3
4
5
// intClass 代表的就是基本数据类型 int类型
Class intClass = int.class;
Class doubleClass = double.class;
Class stringClass3 = String.class;
Class userClass3 = User.class;

第四种方式:①通过类加载器获取

1
2
3
ClassLoader classLoader = ClassLoader.getSystemClassLoader();

Class clazz = classLoader.loadClass(“全限定类名”);

类加载器也是对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 获取类加载器对象(获取的是 系统类加载器/应用类加载器 )
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();

// jdk.internal.loader.ClassLoaders$AppClassLoader@36baf30c
// 这个类加载器是负责加载 classpath 中的字节码文件的。
//System.out.println(systemClassLoader);

// 加载类:但是这个加载过程只是将类加载过程中的前两步完成了,第三步的初始化没做。
// 什么时候做初始化?在这个类真正的被第一次使用的时候。
Class<?> aClass = systemClassLoader.loadClass("com.powernode.javase.reflect.User");

System.out.println(aClass.newInstance());

// 这种方式会走完类加载的全部过程,三步齐全
//Class clazz = Class.forName("com.powernode.javase.reflect.User");

Class.forName和classLoader.loadClass()的区别?

==Class.forName():类加载时会进行初始化。==

==classLoader.loadClass():类加载时不会进行初始化,直到第一次使用该类。==

反射作用的体现

实例化对象

1
2
3
4
5
6
7
8
// 获取到Class类型的实例之后,可以实例化对象
// 通过反射机制实例化对象
Class userClass = Class.forName("com.powernode.javase.reflect.User"); // userClass 代表的就是 User类型。

// 通过userClass来实例化User类型的对象
// 底层实现原理是:调用了User类的无参数构造方法完成了对象的实例化。
// 要使用这个方法实例化对象的话,必须保证这个类中是存在无参数构造方法的。如果没有无参数构造方法,则出现异常:java.lang.InstantiationException
User user = (User)userClass.newInstance();

读取属性配置文件

==读取属性配置文件,获取类名,通过反射机制实例化对象。==

通过这个案例的演示就知道反射机制是灵活的。这个程序可以做到对象的动态创建。

只要修改属性配置文件就可以完成不同对象的实例化。

classObj.newInstance();已经过时

1
2
3
4
5
6
7
8
9
10
11
12
13
// 资源绑定器
ResourceBundle bundle = ResourceBundle.getBundle("com.powernode.javase.reflect.classInfo");
//上面这个是一个属性的配置文件
// 通过key获取value
String className = bundle.getString("className");

// 通过反射机制实例化对象
Class classObj = Class.forName(className);

// 实例化
Object obj = classObj.newInstance();

System.out.println(obj);

反射Field

==关于反射机制中的 java.lang.reflect.Field(代表的是一个类中的字段/属性)==

Field[] fields = vipClass.getDeclaredFields();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Vip {
// Field
public String name;

private int age;

protected String birth;

boolean gender;

public static String address = "北京海淀";

public static final String GRADE = "金牌";
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 获取Vip类
Class vipClass = Class.forName("com.powernode.javase.reflect.Vip");

/*// 获取Vip类中所有 public 修饰的属性/字段
Field[] fields = vipClass.getFields();
System.out.println(fields.length);

// 遍历数组
for(Field field : fields){
System.out.println(field.getName());
}*/

// 获取Vip类中所有的属性/字段,包括私有的
Field[] fields = vipClass.getDeclaredFields();

for(Field field : fields){
// 获取属性名
System.out.println(field.getName());
// 获取属性类型
Class fieldType = field.getType();
// 获取属性类型的简单名称(不带包名的)
System.out.println(fieldType.getSimpleName());
// 获取属性的修饰符
//System.out.println(field.getModifiers());
System.out.println(Modifier.toString(field.getModifiers()));
}

==System.out.println(Modifier.toString(field.getModifiers()));==

反编译(反射)类的字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// 获取String类
Class stringClass = Class.forName("com.powernode.javase.reflect.Vip");

// 字符串拼接
StringBuilder sb = new StringBuilder();

// 获取类的修饰符
sb.append(Modifier.toString(stringClass.getModifiers()));

sb.append(" class ");

//sb.append(stringClass.getSimpleName());
sb.append(stringClass.getName());

sb.append(" extends ");

// 获取当前类的父类
sb.append(stringClass.getSuperclass().getName());

// 获取当前类的实现的所有接口
Class[] interfaces = stringClass.getInterfaces();
if(interfaces.length > 0){
sb.append(" implements ");
for (int i = 0; i < interfaces.length; i++) {
Class interfaceClass = interfaces[i];
sb.append(interfaceClass.getName());
if(i != interfaces.length - 1){
sb.append(",");
}
}
}

sb.append("{\n");

// 获取所有属性
Field[] fields = stringClass.getDeclaredFields();
for (Field field : fields){
sb.append("\t");
sb.append(Modifier.toString(field.getModifiers()));
sb.append(" ");
sb.append(field.getType().getName());
sb.append(" ");
sb.append(field.getName());
sb.append(";\n");
}

sb.append("}");

// 输出
System.out.println(sb);

通过反射机制如何访问Field,如何给属性赋值,如何读取属性的值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// 如果不使用反射机制,怎么访问对象的属性?
Customer customer = new Customer();

// 修改属性的值(set动作)
// customer要素一
// name要素二
// "张三"要素三
customer.name = "张三";

// 读取属性的值(get动作)
// 读取哪个对象的哪个属性
System.out.println(customer.name);

// 如果使用反射机制,怎么访问对象的属性?
// 获取类
Class clazz = Class.forName("com.powernode.javase.reflect.Customer");

// 获取对应的Field
Field ageField = clazz.getDeclaredField("age");

// 调用方法打破封装
ageField.setAccessible(true);
//是的age这个field是可以被获得的

// 修改属性的值
// 给对象属性赋值三要素:给哪个对象 的 哪个属性 赋什么值
ageField.set(customer, 30);
//属性 对象 值

// 读取属性的值
System.out.println("年龄:" + ageField.set(customer, 30););

// 通过反射机制给name属性赋值,和读取name属性的值
Field nameField = clazz.getDeclaredField("name");
// 修改属性name的值
nameField.set(customer, "李四");
// 读取属性name的值
System.out.println(nameField.get(customer));

1.获取类

1
Class clazz = Class.forName("com.powernode.javase.reflect.Customer");

2.获取相对于的field

1
Field ageField = clazz.getDeclaredField("age");

3.调用方法打破封装

1
2
3
// 调用方法打破封装
ageField.setAccessible(true);
//是的age这个field是可以被获得的

4.修改属性的值

1
ageField.set(customer, 30);

5.读取属性的值

1
ageField.get(customer);

反射Method

反编译(反射)类的Method

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class UserService {

/*public void login(){

}*/

/**
* 登录系统的方法
* @param username 用户名
* @param password 密码
* @return true表示登录成功,false表示失败
*/
public boolean login(String username, String password){
/*if("admin".equals(username) && "123456".equals(password)){
return true;
}
return false;*/
return "admin".equals(username) && "123456".equals(password);
}

public String concat(String s1, String s2, String s3){
return s1 + s2 + s3;
}

/**
* 退出系统的方法
*/
public void logout(){
System.out.println("系统已安全退出!");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 获取类
Class clazz = Class.forName("com.powernode.javase.reflect.UserService");

// 获取所有的方法,包含私有的方法
Method[] methods = clazz.getDeclaredMethods();
//System.out.println(methods.length);

// 遍历数组
for(Method method : methods){
// 方法修饰符
System.out.println(Modifier.toString(method.getModifiers()));
// 方法返回值类型
System.out.println(method.getReturnType().getName());
// 方法名
System.out.println(method.getName());
// 方法的参数列表
/*Class<?>[] parameterTypes = method.getParameterTypes();
for (Class parameterType : parameterTypes){
System.out.println(parameterType.getName());
}*/

Parameter[] parameters = method.getParameters();
for (Parameter parameter : parameters){
System.out.println(parameter.getType().getName());
System.out.println(parameter.getName());// arg0, arg1, arg2......
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
/**
* 反射一个类中所有的方法,然后进行拼接字符串。
*/
public class ReflectTest09 {
public static void main(String[] args) throws Exception{
StringBuilder sb = new StringBuilder();
Class stringClass = Class.forName("com.powernode.javase.reflect.UserService");
// 获取类的修饰符
sb.append(Modifier.toString(stringClass.getModifiers()));
sb.append(" class ");
// 获取类名
sb.append(stringClass.getName());
// 获取父类名
sb.append(" extends ");
sb.append(stringClass.getSuperclass().getName());
// 获取父接口名
Class[] interfaces = stringClass.getInterfaces();
if(interfaces.length > 0){
sb.append(" implements ");
for (int i = 0; i < interfaces.length; i++) {
sb.append(interfaces[i].getName());
if(i != interfaces.length - 1){
sb.append(",");
}
}
}
sb.append("{\n");

// 类体
// 获取所有的方法
Method[] methods = stringClass.getDeclaredMethods();
for(Method method : methods){
sb.append("\t");
// 追加修饰符
sb.append(Modifier.toString(method.getModifiers()));
// 追加返回值类型
sb.append(" ");
sb.append(method.getReturnType().getName());
// 追加方法名
sb.append(" ");
sb.append(method.getName());
sb.append("(");
// 追加参数列表
Parameter[] parameters = method.getParameters();
for (int i = 0; i < parameters.length; i++) {
Parameter parameter = parameters[i];
sb.append(parameter.getType().getName());
sb.append(" ");
sb.append(parameter.getName());
if(i != parameters.length - 1){
sb.append(",");
}
}
sb.append("){}\n");
}

sb.append("}");

// 输出
System.out.println(sb);

}
}

用反射调用类的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// 不使用反射机制怎么调用方法?
// 创建对象
UserService userService = new UserService();

// 调用方法
// 分析:调用一个方法需要几个要素?四要素
// 调用哪个对象的哪个方法,传什么参数,返回什么值
boolean isSuccess = userService.login("admin", "123456");
System.out.println(isSuccess ? "登录成功" : "登录失败");

// 调用方法
userService.logout();



/******************************************************************************************************/

// 通过反射机制调用login方法
// 获取Class
Class clazz = Class.forName("com.powernode.javase.reflect.UserService");

// 获取login方法,提供方法名,提供形参列表
Method loginMethod = clazz.getDeclaredMethod("login", String.class, String.class);

// 调用login方法
Object retValue = loginMethod.invoke(userService, "admin", "123456");
System.out.println(retValue);

// 调用logout方法
Method logoutMethod = clazz.getDeclaredMethod("logout");
logoutMethod.invoke(userService);
// 获取Class
Class clazz = Class.forName("com.powernode.javase.reflect.UserService");

1.获取login方法(提供方法名,提供形参列表)

1
Method loginMethod = clazz.getDeclaredMethod("login", String.class, String.class);

2.调用login方法()

1
2
3
//返回值            方法                对象         形参1     形参2
Object retValue = loginMethod.invoke(userService, "admin", "123456");
System.out.println(retValue);

3.调用logout方法

1
2
Method logoutMethod = clazz.getDeclaredMethod("logout");
logoutMethod.invoke(userService);

反射Constructor

通过反射机制获取一个类中所有的构造方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
	StringBuilder sb = new StringBuilder();
// 获取类
Class clazz = Class.forName("java.lang.String");
// 类的修饰符
sb.append(Modifier.toString(clazz.getModifiers()));
sb.append(" class ");
// 类名
sb.append(clazz.getName());
sb.append(" extends ");
// 父类名
sb.append(clazz.getSuperclass().getName());
// 实现的接口
Class[] interfaces = clazz.getInterfaces();
if(interfaces.length > 0) {
sb.append(" implements ");
for (int i = 0; i < interfaces.length; i++) {
sb.append(interfaces[i].getName());
if(i != interfaces.length - 1){
sb.append(",");
}
}
}
sb.append("{\n");

//类体
// 获取所有的构造方法
Constructor[] cons = clazz.getDeclaredConstructors();
// 遍历所有的构造方法
for(Constructor con : cons){
sb.append("\t");
// 构造方法修饰符
sb.append(Modifier.toString(con.getModifiers()));
sb.append(" ");
// 构造方法名
sb.append(con.getName());
sb.append("(");

// 构造方法参数列表
Parameter[] parameters = con.getParameters();
for (int i = 0; i < parameters.length; i++) {
Parameter parameter = parameters[i];
sb.append(parameter.getType().getName());
sb.append(" ");
sb.append(parameter.getName());
if(i != parameters.length - 1){
sb.append(",");
}
}

sb.append("){}\n");
}

sb.append("}");

System.out.println(sb);
}

通过反射机制调用构造方法来创建对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 不使用反射机制的时候,怎么创建的对象?
Order order1 = new Order();
System.out.println(order1);

Order order2 = new Order("1111122222", 3650.5, "已完成");
System.out.println(order2);



/***************************************************************************************************/

// 通过反射机制来实例化对象?
Class clazz = Class.forName("com.powernode.javase.reflect.Order");
// 这种方式依赖的是必须有一个无参数构造方法。如果没有会出现异常!
// 在Java9的时候,这个方法被标注了已过时。不建议使用了。
/*Object obj = clazz.newInstance();
System.out.println(obj);*/

// 获取Order的无参数构造方法
Constructor defaultCon = clazz.getDeclaredConstructor();
// 调用无参数构造方法实例化对象
Object obj = defaultCon.newInstance();
System.out.println(obj);

// 获取三个参数的构造方法
Constructor threeArgsCon = clazz.getDeclaredConstructor(String.class, double.class, String.class);
// 调用三个参数的构造方法
Object obj1 = threeArgsCon.newInstance("5552454222", 6985.0, "未完成");
System.out.println(obj1);

1. 通过反射机制来实例化对象?

1
Class clazz = Class.forName("com.powernode.javase.reflect.Order");

2. 获取Order的无参数构造方法

1
Constructor defaultCon = clazz.getDeclaredConstructor();

3. 获取三个参数的构造方法

1
Constructor threeArgsCon = clazz.getDeclaredConstructor(String.class, double.class, String.class);

4.调用无参数构造方法实例化对象

1
2
Object obj = defaultCon.newInstance();
System.out.println(obj);

5.调用三个参数的构造方法

1
2
Object obj1 = threeArgsCon.newInstance("5552454222", 6985.0, "未完成");
System.out.println(obj1);

模拟框架的部分实现

config.properties

1
2
3
4
className=com.powernode.javase.reflect.UserService
methodName=concat
parameterTypes=java.lang.String,java.lang.String,java.lang.String
parameterValues=abc,def,xyz

模拟框架的部分代码。通过读取属性配置文件,获取类信息,方法信息,然后通过反射机制调用方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 读取属性配置文件
ResourceBundle bundle = ResourceBundle.getBundle("com.powernode.javase.reflect.config");
String className = bundle.getString("className");
String methodName = bundle.getString("methodName");
String parameterTypes = bundle.getString("parameterTypes");
String parameterValues = bundle.getString("parameterValues");

// 通过反射机制调用方法
// 创建对象(依赖无参数构造方法)
Class<?> clazz = Class.forName(className);
Constructor<?> defaultCon = clazz.getDeclaredConstructor();
Object obj = defaultCon.newInstance();

// 获取方法
// java.lang.String,java.lang.String
String[] strParameterTypes = parameterTypes.split(",");
Class[] classParameterTypes = new Class[strParameterTypes.length];
for (int i = 0; i < strParameterTypes.length; i++) {
classParameterTypes[i] = Class.forName(strParameterTypes[i]);
}
Method method = clazz.getDeclaredMethod(methodName, classParameterTypes);

// 调用方法
// parameterValues=admin,123456
Object retValue = method.invoke(obj, parameterValues.split(","));

System.out.println(retValue);

类加载及双亲委派机制

类的加载过程

image-20240304215603299

image-20240304215317903

①装载(loading)

​ 类加载器负责将类的class文件读入内存,并创建一个java.lang.Class对象

②连接(linking)

1.验证(Verify)

1
确保加载类的信息符合JVM规范。

2.准备(Prepare)

1
2
3
4
5
正式为静态变量在方法区中开辟存储空间并设置默认值

public static int k = 10; 此时:k会赋值0

public static final int f = 10; 此时: f会赋值10

3.解析(Resolve)

1
将虚拟机常量池内的符号引用替换为直接引用(地址)的过程。

③初始化(initialization)

1
静态变量赋值,静态代码块执行

低版本的JDK中类加载器的名字:

​ 启动类加载器:负责加载rt.jar

​ 扩展类加载器:ext/*.jar

​ 系统类加载器:classpath

image-20240304215407135

类加载器

①虚拟机内部提供了三种类加载器(Java9+):

  • 启动类加载器(BootstrapClassLoader):加载Java最核心的类,例如String
  • 平台类加载器(PlatformClassLoader):加载Java平台扩展的类库,例如解析XML的
  • 应用类加载器(AppClassLoader):加载classpath中的自己写的 (系统类加载器/应用类加载器 )
  • 同时我们还可以自定义一个类加载器(UserClassLoader)用户类加载器

②获取类加载器可以通过 getParent()方法一级一级获取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 通过自定义的类获取的类加载器是:应用类加载器。
ClassLoader appClassLoader = ReflectTest15.class.getClassLoader();
System.out.println("应用类加载器:" + appClassLoader);

// 获取应用类加载器
ClassLoader appClassLoader2 = ClassLoader.getSystemClassLoader();
System.out.println("应用类加载器:" + appClassLoader2);

// 获取应用类加载器
ClassLoader appClassLoader3 = Thread.currentThread().getContextClassLoader();
System.out.println("应用类加载器:" + appClassLoader3);




/*******************************************************************************************/
// 通过 getParent() 方法可以获取当前类加载器的 “父 类加载器”。
// 获取平台类加载器。
System.out.println("平台类加载器:" + appClassLoader.getParent());
/***********************************************************************************************/
// 获取启动类加载器。
// 注意:启动类加载器负责加载的是JDK核心类库,这个类加载器的名字看不到,直接输出的时候,结果是null。
System.out.println("启动类加载器:" + appClassLoader.getParent().getParent())

启动类加载器

1
System.out.println("启动类加载器:" + appClassLoader.getParent().getParent())

平台类加载器

1
System.out.println("平台类加载器:" + appClassLoader.getParent());

应用类加载器

1
2
3
ClassLoader appClassLoader = ReflectTest15.class.getClassLoader();
ClassLoader appClassLoader2 = ClassLoader.getSystemClassLoader();
ClassLoader appClassLoader3 = Thread.currentThread().getContextClassLoader();

双亲委派机制

image-20240304221342040

①某个类加载器接收到加载类的任务时,通常委托给“父 类加载”完成加载。

②最“父 类加载器”无法加载时,一级一级向下委托加载任务。

③作用:

​ 保护程序的安全。

​ 防止类加载重复。

通过反射获取父类的泛型

1.Animal

1
2
3
4
5
6
7
8
/**
* 在类上定义泛型
* @param <X>
* @param <Y>
* @param <Z>
*/
public class Animal<X, Y, Z> {
}

2.cat

1
2
public class Cat extends Animal<String, Integer, Double>{
}

3.获取父类的泛型(x,y,z)Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/**
* 获取父类的泛型信息
*/
public class Test {
public static void main(String[] args) {
// 获取类
Class<Cat> catClass = Cat.class;

// 获取当前类的父类泛型
Type genericSuperclass = catClass.getGenericSuperclass();
//System.out.println(genericSuperclass instanceof Class);//true
//System.out.println(genericSuperclass instanceof ParameterizedType);//false


// 如果父类使用了泛型
if(genericSuperclass instanceof ParameterizedType){
// 转型为参数化类型
ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
// 获取泛型数组
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
// 遍历泛型数组
for(Type a : actualTypeArguments){
// 获取泛型的具体类型名
System.out.println(a.getTypeName());
}
}
}
}

通过反射获取接口的泛型

1.flyable

1
2
public interface Flyable<X, Y> {
}

2.Mouse

1
2
3
4
5
6
public class Mouse implements Flyable<String, Integer>, Comparable<Mouse>{
@Override
public int compareTo(Mouse o) {
return 0;
}
}

3.获取Type[] genericInterfaces = mouseClass.getGenericInterfaces();

1
2
3
4
5
6
7
8
9
10
11
12
13
Class<Mouse> mouseClass = Mouse.class;
// 获取接口上的泛型
Type[] genericInterfaces = mouseClass.getGenericInterfaces();
for (Type g : genericInterfaces) {
// 使用了泛型
if(g instanceof ParameterizedType){
ParameterizedType parameterizedType = (ParameterizedType) g;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
for(Type a : actualTypeArguments){
System.out.println(a.getTypeName());
}
}
}

通过反射获取属性的泛型

1.user

1
2
3
public class User {
private Map<Integer, String> map;
}

2.获取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Test {
public static void main(String[] args) throws Exception{
// 获取这个类
Class<User> userClass = User.class;
// 获取属性上的泛型,需要先获取到属性
Field mapField = userClass.getDeclaredField("map"); // 获取公开的以及私有的
// 获取这个属性上的泛型
Type genericType = mapField.getGenericType();
// 用泛型了
if(genericType instanceof ParameterizedType){
ParameterizedType parameterizedType = (ParameterizedType) genericType;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
for(Type a : actualTypeArguments){
System.out.println(a.getTypeName());
}
}
}
}

通过反射获取方法参数的泛型

1.Myclass

1
2
3
4
5
6
7
public class MyClass {

public Map<Integer, Integer> m(List<String> list, List<Integer> list2){
return null;
}

}

2.获取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 获取类
Class<MyClass> myClassClass = MyClass.class;

// 获取方法
Method mMethod = myClassClass.getDeclaredMethod("m", List.class, List.class);

// 获取方法参数上的泛型
Type[] genericParameterTypes = mMethod.getGenericParameterTypes();
for(Type g : genericParameterTypes){
// 如果这个参数使用了泛型
if(g instanceof ParameterizedType){
ParameterizedType parameterizedType = (ParameterizedType) g;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
for(Type a : actualTypeArguments){
System.out.println(a.getTypeName());
}
}
}

// 获取方法返回值上的泛型
Type genericReturnType = mMethod.getGenericReturnType();
if(genericReturnType instanceof ParameterizedType){
ParameterizedType parameterizedType = (ParameterizedType) genericReturnType;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
for(Type a : actualTypeArguments){
System.out.println(a.getTypeName());
}
}

通过反射获取构造函数的泛型

1
2
public User(Map<String ,Integer> map){
}
1
2
3
4
5
6
7
8
9
10
11
12
Class<User> userClass = User.class;
Constructor<User> con = userClass.getDeclaredConstructor(Map.class);
Type[] genericParameterTypes = con.getGenericParameterTypes();
for(Type g :genericParameterTypes){
if(g instanceof ParameterizedType){
ParameterizedType parameterizedType = (ParameterizedType) g;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
for(Type a : actualTypeArguments){
System.out.println(a.getTypeName());
}
}
}