Java 反射(Reflect)详解
什么是反射?
反射是指Java程序可以检查自身的能力,并且在运行时获取和操作自身的类、接口、方法和属性等信息。Java反射提供了一种机制使得一个程序在运行期间可以获取自身的信息并且可以操作该类的内部属性、方法和构造方法。
反射的作用
反射主要有如下应用场景:
- 动态创建对象或获取已有对象的信息;
- 调用对象的方法;
- 访问和修改类的成员变量等。
反射可以做很多的事情,例如动态创建对象、动态获取类的方法或属性信息、动态调用方法,还可以实现IOC容器、代理对象等功能。
反射相关概念
在了解反射之前,首先需要了解以下三个概念:
- Class类:用于表示类或接口的实体,并提供了获取类或接口的变量、属性、方法和构造方法等信息的功能。
- Field类:用于描述类或接口中的属性信息。
- Method类:用于描述类或接口中的方法信息。
反射API的使用
获取Class类实例对象
Class<?> clazz = Class.forName("java.lang.String");
获取类的属性
Class<?> clazz = Class.forName("com.example.User");
Field[] fields = clazz.getDeclaredFields(); // 获取类中所有属性
for (Field field : fields) {
System.out.println(field.getName()); // 输出属性名
}
获取类的方法
Class<?> clazz = Class.forName("com.example.User");
Method[] methods = clazz.getMethods(); // 获取类中所有方法
for (Method method : methods) {
System.out.println(method.getName()); // 输出方法名
}
调用方法
Class<?> clazz = Class.forName("com.example.User");
Object obj = clazz.newInstance();
Method method = clazz.getDeclaredMethod("setName", String.class);
method.invoke(obj, "jack"); // 调用 setName 方法设置属性值
示例说明一:动态代理
动态代理是指在程序运行时生成代理类、代理对象,代替原有的类或对象,实现同样的接口或方法,并对委托的真实对象进行控制。在Java中,动态代理是基于反射实现的,即动态代理生成的类是基于原来类的实现,因此我们需要通过反射得到原来类的接口或方法信息。
// 定义接口
public interface UserService {
String sayHello(String msg);
}
// 实现接口
public class UserServiceImpl implements UserService {
@Override
public String sayHello(String msg) {
return "Hello " + msg + "!";
}
}
// 生成代理类
public class UserServiceProxy implements InvocationHandler {
private Object target;
public Object bind(Object target) {
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before invoke method");
Object result = method.invoke(target, args);
System.out.println("after invoke method");
return result;
}
}
// 调用代理类的方法
public class Main {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
UserServiceProxy proxy = new UserServiceProxy();
UserService proxyService = (UserService) proxy.bind(userService);
proxyService.sayHello("Jack");
}
}
示例说明二:使用注解实现自定义ORM框架
ORM (Object Relational Mapping)框架是指通过反射实现Java对象与数据库表之间的映射。在Java程序中,可以使用注解定义与数据库表对应的实体类对象,并使用反射读取注解信息。同时,也可以使用Class类提供的一些方法获取实体类对象中的成员变量和成员方法,并使用数据库操作API实现数据库的CRUD操作。
// 定义注解
@Target(ElementType.FIELD) // 表示注解用在类的属性上
@Retention(RetentionPolicy.RUNTIME) // 表示注解在运行时保留
public @interface Column {
String name() default ""; // 数据库字段名称
}
// 定义实体类
public class User {
@Column(name = "id")
private int id;
@Column(name = "name")
private String name;
@Column(name = "age")
private int age;
}
// 读取注解信息
public static String getColumnValue(Object obj, String columnName) throws Exception {
Class<?> clazz = obj.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(Column.class)) {
Column column = field.getAnnotation(Column.class);
if (column.name().equals(columnName)) {
field.setAccessible(true);
return String.valueOf(field.get(obj)); // 返回指定属性名的属性值
}
}
}
return null;
}
// 使用数据库操作API实现数据库的CRUD操作
public static void save(Object obj) throws Exception {
Class<?> clazz = obj.getClass();
StringBuilder sb = new StringBuilder();
StringBuilder sbValue = new StringBuilder();
sb.append("insert into ").append(clazz.getSimpleName()).append("(");
sbValue.append(" values(");
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(Column.class)) {
Column column = field.getAnnotation(Column.class);
sb.append(column.name()).append(",");
sbValue.append("'").append(getColumnValue(obj, column.name())).append("',");
}
}
sb.deleteCharAt(sb.length() - 1).append(")");
sbValue.deleteCharAt(sbValue.length() - 1).append(")");
String sql = sb.toString() + sbValue.toString();
// 执行数据库插入操作
System.out.println(sql);
}
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java 反射(Reflect)详解 - Python技术站