Day1 Java 反射
Java反射
DI的实现需要用到Java反射技术。
什么是反射?
反射:
- 没有通过new关键字直接创建对象;
- 根据类型元数据(包括类型的所有描述信息,如类名称、属性名称和属性类型、方法等),来间接地创建类对象,或调用类的方法;
- 可以动态地操作类;
类长什么样儿?
参见:https://docs.oracle.com/javase/specs/jvms/se13/html/jvms-4.html#jvms-4.1
ClassFile {
u4 magic;
u2 minor_version;
u2 major_version;
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count-1];
u2 access_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;
u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
}
反射API
反射能做什么?
- 在运行时判断类型;
- 在运行时创建类对象;
- 在运行时判断类是否有某个成员变量或方法;
- 在运行时设置类属性值,或者调用对象的方法;
- 动态代理
创建对象
- 获取类类型(类元数据信息),Class类型对象
Class<?> cls = Class.forName("com.bailiban.day1.helloworld.model.User"); - 使用Class对象,获取构造函数,Constructor类型对象
Constructor<?>[] constructors = cls.getDeclaredConstructors(); - 使用Constructor对象,创建目标对象
User user = constructors[0].newInstance();
示例代码:
public class ConstructorTest {
public static void main(String[] args) throws Exception {
String className = "com.bailiban.day1.helloworld.model.User";
// 1. 获取User的类类型(类元数据信息)
Class<?> cls = Class.forName(className);
// 2. 获取并遍历User所有构造函数
System.out.println("--------获取并遍历User所有构造函数");
Constructor<?>[] constructors = cls.getDeclaredConstructors();
for (Constructor<?> cons: constructors) {
// 获取限定符,这里全部是public
String modifier = Modifier.toString(cons.getModifiers());
System.out.print(modifier + " " + cls.getSimpleName() + "(");
// 获取对应构造函数的参数类型和名称
String paramStr = "";
Parameter[] parameters = cons.getParameters();
for (Parameter param: parameters) {
paramStr += param.getType().getName() + " " + param.getName() + ", ";
}
if (!paramStr.equals(""))
paramStr = paramStr.substring(0, paramStr.length()-2);
System.out.println(paramStr + ");");
}
// 3. 通过无参构造函数,创建对象
System.out.println("---------通过无参构造函数,创建对象");
User user = (User) constructors[0].newInstance();
user.setId(1001);
user.setName("Jim");
System.out.println(user);
// 4. 通过有参构造函数,创建对象
System.out.println("---------通过有参构造函数,创建对象");
User user1 = (User) constructors[1].newInstance(1002, "David");
System.out.println(user1);
}
}
运行结果:
--------获取并遍历User所有构造函数
public User();
public User(int id, java.lang.String name);
---------通过无参构造函数,创建对象
User{id=1001, name='Jim'}
---------通过有参构造函数,创建对象
User{id=1002, name='David'}
设置属性值
- 获取类类型(类元数据信息),Class类型对象
Class<?> cls = Class.forName("com.bailiban.day1.helloworld.model.User"); - 使用Class对象,获取成员变量,Field类型对象
Field[] fields = cls.getDeclaredFields(); - 使用反射给属性赋值
Field field = cls.getDeclaredField("id");
field.setAccessible(true);
field.set(user, 1001);
示例代码:
public class FieldTest {
public static void main(String[] args) throws Exception {
// 1. 获取User的类类型(类元数据信息)
Class<?> cls = Class.forName("com.bailiban.day1.helloworld.model.User");
// 2. 根据Class对象获取User的成员变量
System.out.println("-----User的成员变量:");
Field[] fields = cls.getDeclaredFields();
for (Field field: fields) {
String modifier = Modifier.toString(field.getModifiers());
System.out.println(modifier + " " + field.getType().getSimpleName() + " " + field.getName() + ";");
}
// 3. 使用反射给属性赋值
System.out.println("-----使用反射给属性赋值:");
User user = (User) cls.getConstructors()[0].newInstance();
Field field = cls.getDeclaredField("id");
field.setAccessible(true);
field.set(user, 1001);
field = cls.getDeclaredField("name");
field.setAccessible(true);
field.set(user, "Jim");
System.out.println(user);
}
}
运行结果:
-----User的成员变量:
private int id;
private String name;
-----使用反射给属性赋值:
User{id=1001, name='Jim'}
调用方法
- 获取类类型(类元数据信息),Class类型对象
Class<?> cls = Class.forName("com.bailiban.day1.helloworld.model.User"); - 使用Class对象,获取对象方法,Method类型对象
Method[] methods = cls.getDeclaredMethods(); - 使用反射调用方法
Method method = cls.getDeclaredMethod("setId", int.class);
method.invoke(user, 1001);
示例代码:
public class MethodTest {
public static void main(String[] args) throws Exception {
// 1. 获取User的类类型(类元数据信息)
Class<?> cls = Class.forName("com.bailiban.day1.helloworld.model.User");
// 2. 根据Class对象获取User的方法
System.out.println("-----User的方法:");
Method[] methods = cls.getDeclaredMethods();
for (Method method: methods) {
String modifier = Modifier.toString(method.getModifiers());
System.out.print(modifier + " " + method.getName() + "(");
// 获取对应构造函数的参数类型和名称
String paramStr = "";
Parameter[] parameters = method.getParameters();
for (Parameter param: parameters) {
paramStr += param.getType().getSimpleName() + " " + param.getName() + ", ";
}
if (!paramStr.equals(""))
paramStr = paramStr.substring(0, paramStr.length()-2);
System.out.println(paramStr + ");");
}
// 3. 使用反射调用方法
System.out.println("-----使用反射调用方法:");
User user = (User) cls.getConstructors()[0].newInstance();
Method method = cls.getDeclaredMethod("setId", int.class);
method.invoke(user, 1001);
method = cls.getDeclaredMethod("setName", String.class);
method.invoke(user, "Jim");
System.out.println(user);
}
}
运行结果:
-----User的方法:
public toString();
public getName();
public getId();
public setName(String name);
public setId(int id);
-----使用反射调用方法:
User{id=1001, name='Jim'}

浙公网安备 33010602011771号