反射介绍

可以不直接new 对象,或调用方法。 用另一种创建某个对象(字符串的方式),或调用某个对象的方法(字符串的方式)。 反射这种间接调用效率肯定是不如直接调用的。

程序不知道具体要创建接口的哪个实现类, 在启动时,通过读取配置文件才知道要创建那个实现类。

先学习语法,然后可以通过结合动态代理加深理解。

反射的场景

一般的开发很少直接用到,不过在各类框架中基本离不开。
另外如果要自研框架,或者对框架定制功能,通常也会用到。

  • spring以xml配置去注册bean
  • 动态代理以及其衍生的各类服务
    • 远程调用
    • 日志,监控
    • 缓存
    • 权限
    • spring-事务注解
  • 使用注解的实现的各种功能
  • 软件破解。。。等等

语法示例

普通的bean

 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
package com.test.base_java;

public class Person {
	private String name;
	Integer age;

	public Person() {
	}

	public Person(String name, Integer age) {
		super();
		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;
	}
}

演示

 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
package com.test.base_java;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Reflect1 {
	public static void main(String[] ss) throws Exception {
		// 1. 获取class对象
		Person p1 = new Person();
		Class class1 = p1.getClass();
		System.out.println("obj.getClass     " + class1.getName());

		String Pname = "com.test.base_java.Person";
		Class class2 = Class.forName(Pname);
		System.out.println("forName     " + class2.getName());

		// 2. 创建对象
		Person p2 = (Person) class1.newInstance();
		p2.setName("zs111");
		System.out.println("2. 创建对象");
		System.out.println(p2);

		// 3. 获取构造器
		Constructor[] constructors = class1.getConstructors();
		System.out.println("3. 类的构造器为");
		for (Constructor cst : constructors) {
			System.out.println(cst);
		}
		// 4. 有参数构造对象
		System.out.println("4. 通过有参构造对象");
		Constructor cst2 = class1.getConstructor(String.class, Integer.class);
		Person p3 = (Person) cst2.newInstance("zs222", 5);
		System.out.println(p3.getName());
		// 5. 打印类的方法
		System.out.println("5. 该类包含的方法");
		Method[] methods = class1.getMethods();
		for (Method method : methods) {
			System.out.println(method.getName());
		}

		// 6. 调用 getName方法
		System.out.println("6. 反射调用方法   ");
		String attr = "name";
		String methodName1 = "get" + initcap(attr);
		String methodName2 = "set" + initcap(attr);
		Method getName = class1.getMethod(methodName1);
		Method setName = class1.getMethod(methodName2, String.class);

		setName.invoke(p1, "zs_p111");
		System.out.println(getName.invoke(p1));

		// 设置属性 直接操作对象p1的name
		System.out.println("7. 直接操作对象的private属性");
		Field[] fields = class1.getFields();
		Field nameField = class1.getDeclaredField(attr);
		nameField.setAccessible(true);
		nameField.set(p1, "zs_p222"); // name为private 需先解锁权限
		System.out.println(nameField.get(p1));

	}

	// 首字母大写 age >> Age
	public static String initcap(String str) {
		return str.substring(0, 1).toUpperCase().concat(str.substring(1));
	}
}

todo-more

泛型,注解等示例