反射

反射

反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。
类的加载过程:
程序经过javac.exe命令后,会生成一个或多个字节码文件(.class),接着使用java.exe命令对某个字节码文件进行解释运行。相当于将某个字节码文件加载到内存中,即类的加载。加载到内存中的类,我们就成为运行时类,此运行时类就作为Class的一个实例。
加载到内存中的运行时类,会缓存一段时间。在此时间内,我们可以通过不同的方式来获取此运行时类。

获取Class实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Test // 获取Class实例
public void test1() throws ClassNotFoundException {
// 方式一:调用运行类属性:.class
Class class0 = Person.class;
System.out.println(class0);
// 方式二:调用运行时类的对象,调用getClass()
Person p1 = new Person();
Class class1 = p1.getClass();
System.out.println(class1);
// 方式三:调用Class的静态方法:forName(String classPath)
Class class2 = Class.forName("reflection.Person");
System.out.println(class2);
// 方式四:使用类加载器:Classloader
ClassLoader classLoader = ClassTest.class.getClassLoader();
Class class3 = classLoader.loadClass("reflection.Person");
System.out.println(class3);
}

调用运行时类指定结构

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
@Test
public void test2() throws Exception {
// 通过反射创建对应的运行时类
Class<Person> class1 = Person.class;
// 创建运行时类的对象
Person p1 = class1.newInstance();
System.out.println(p1);
// 获取运行时类的属性getField(String fieldName),只能获取权限为public的属性
Field id = class1.getField("id");
// 通常使用getDeclaredField(String FieldName)获取运行时类的属性
Field name = class1.getDeclaredField("name");
name.setAccessible(true);// 表示当前属性时可访问的
// 设置属性值 set(实例对象,属性值)
id.set(p1,10001);
name.set(p1,"Tony");

// 获取属性值
int p1_id = (int) id.get(p1);
System.out.println(p1_id);// 10001
System.out.println(name.get(p1));// Tony
System.out.println(p1);// Person{id=10001, name='Tony', age=0}

// 获取运行时类方法 getDeclaredMethod(方法名,指定方法的形参列表)
Method setAge = class1.getDeclaredMethod("setAge", int.class);
setAge.setAccessible(true);// 指明该方法可访问
// 执行运行时类方法 invoke(对象实例,实参列表)
// invoke()的返回值即为对应类中调用方法的返回值
setAge.invoke(p1,24);
System.out.println(p1);// Person{id=10001, name='Tony', age=24}

// 获取指定构造器
Constructor con = class1.getDeclaredConstructor(int.class,String.class,int.class);
con.setAccessible(true);
Person p2 = (Person) con.newInstance(1002,"Taylor",18);
System.out.println(p2);// Person{id=1002, name='Taylor', age=18}
}