类的加载机制与反射(二)

时间不会辜负每一个平静努力的人!

欢迎来到周建的博客: 共同致力于技术分享与交流

通过反射查看类的信息

Java程序中许多对象在运行时都会出现两种类型:编译时类型和运行时类型
例如:Person p = new Student();
编译类型为:Person
运行类型为:Student

为了解决这种问题,有两种方式:

  • 假设在编译时和运行时都完全知道类型的具体信息,在这种情况下,可以先使用instanceof 运算符进行判断
  • 编译时无法知道对象和类属于那些类,程序只能依靠运行时信息来发现该对象和类的真实信息,这就必须通过反射

1. 获得 Class 对象

java程序中获得 Class 对象有三种方式

  • 使用Class 类的forName(String clazzName)静方法。必须是完整包名。
  • 调用某个类的class属性来获取该类的 Class 对象。
  • 调用某个对象的getClass() 方法。

2. 从 Class 对象中获取信息

具体使用查阅API文档,下面以一个例子来说明

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
64
65
66
67
68
69
70
71
package com.example;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/**
* Created by zhoujian on 2017/4/5.
*/
public class ClassTest {
private ClassTest() {
System.out.println("执行无参构造函数");
}
public ClassTest(String name) {
System.out.println("执行有参构造函数");
}
public void method() {
System.out.println("执行无参method方法");
}
public void method(String str) {
System.out.println("执行有参method方法");
}
public static void main(String[] args) {
//获取Class对象
Class<ClassTest> aClass = ClassTest.class;
//获取Class对象所对应类的全部构造器
Constructor<?>[] constructors = aClass.getDeclaredConstructors();
System.out.println("ClassTest的全部构造器如下:");
for (Constructor<?> constructor : constructors) {
System.out.println(constructor);
}
//获取Class对象所对应类的全部public构造器
Constructor<?>[] cons = aClass.getConstructors();
System.out.println("-----------------------------------");
System.out.println("ClassTest的全部public构造器如下:");
for (Constructor<?> c : cons) {
System.out.println(c);
}
//获取Class对象所对应类的全部public方法
Method[] methods = aClass.getMethods();
System.out.println("-----------------------------------");
System.out.println("ClassTest的全部public方法如下:");
for (Method method : methods) {
System.out.println(method);
}
//获取Class对象所对应类的指定方法
try
{
Method meth = aClass.getMethod("method", String.class);
System.out.println("-----------------------------------");
System.out.println("ClassTest里带一个字符串参数的method方法:"+meth);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}

运行结果如下:

Snip20170405_1.png

3. Java8 新增的方法参数反射

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
package com.example;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.List;
/**
* Created by zhoujian on 2017/4/3.
*/
public class TextA
{
public void rep(String string, List<String> list)
{
}
public static void main(String[] args) {
Class<TextA> aClass = TextA.class;
try {
//获取带有两个参数的 rep方法
Method rep = aClass.getMethod("rep", String.class, List.class);
//获取指定方法参数个数
int count = rep.getParameterCount();
System.out.println("rep方法参数个数:" + count);
//获取rep 方法的所有参数信息
Parameter[] parameters = rep.getParameters();
int index = 1;
for (Parameter parameter : parameters) {
//方法返回该类的class文件中是否包含了方法的形参名信息
System.out.println("----第" + index++ + "个参数信息---");
System.out.println("参数名:" + parameter.getName());
System.out.println("形参类型:" + parameter.getType());
System.out.println("泛型类型:" + parameter.getParameterizedType());
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}

Snip20170405_3.png