反射机制详解
一、知识概述
反射(Reflection)是Java语言的特性之一,它允许程序在运行时获取类的内部信息,并直接操作对象的属性和方法。反射是框架开发的基石,Spring、MyBatis、Hibernate等主流框架都大量依赖反射机制。
反射能做什么?
| 功能 | 说明 |
|---|---|
| 获取类信息 | 类名、修饰符、父类、接口、注解 |
| 操作字段 | 获取字段、修改字段值(包括私有字段) |
| 调用方法 | 调用任意方法(包括私有方法) |
| 创建对象 | 无需new关键字,动态创建实例 |
| 动态代理 | 运行时生成代理类 |
反射的应用场景
- 框架开发:Spring IoC、AOP
- ORM映射:Hibernate、MyBatis
- 序列化/反序列化:Jackson、Gson
- 动态代理:Retrofit、动态数据源
- 测试框架:JUnit、Mockito
二、知识点详细讲解
2.1 获取Class对象
Class对象是反射的入口,有四种获取方式:
/**
* 获取Class对象的四种方式
*/
public class GetClassDemo {
public static void main(String[] args) throws Exception {
// 方式1:通过类名.class(编译时已知类型)
Class<String> clazz1 = String.class;
System.out.println("方式1: " + clazz1.getName());
// 方式2:通过对象.getClass()(运行时已知对象)
String str = "Hello";
Class<? extends String> clazz2 = str.getClass();
System.out.println("方式2: " + clazz2.getName());
// 方式3:通过Class.forName()(全限定类名,动态加载)
Class<?> clazz3 = Class.forName("java.lang.String");
System.out.println("方式3: " + clazz3.getName());
// 方式4:通过类加载器(适用于内部类等特殊情况)
ClassLoader loader = Thread.currentThread().getContextClassLoader();
Class<?> clazz4 = loader.loadClass("java.lang.String");
System.out.println("方式4: " + clazz4.getName());
// 验证:同一个类的Class对象是唯一的
System.out.println("clazz1 == clazz2: " + (clazz1 == clazz2)); // true
System.out.println("clazz2 == clazz3: " + (clazz2 == clazz3)); // true
}
}
2.2 类信息获取
import java.lang.annotation.*;
import java.lang.reflect.*;
/**
* 类信息获取示例
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
String value();
}
@MyAnnotation("示例类")
class Person implements Comparable<Person>, Cloneable {
private String name;
public int age;
public Person() {}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Person o) {
return this.age - o.age;
}
}
public class ClassInfoDemo {
public static void main(String[] args) {
Class<Person> clazz = Person.class;
// 基本信息
System.out.println("=== 基本信息 ===");
System.out.println("类名: " + clazz.getName()); // 全限定名
System.out.println("简单类名: " + clazz.getSimpleName()); // 简单名称
System.out.println("包名: " + clazz.getPackage().getName());
System.out.println("修饰符: " + Modifier.toString(clazz.getModifiers()));
// 父类
System.out.println("\n=== 父类 ===");
Class<? super Person> superClass = clazz.getSuperclass();
System.out.println("父类: " + superClass.getName());
// 接口
System.out.println("\n=== 实现的接口 ===");
Class<?>[] interfaces = clazz.getInterfaces();
for (Class<?> iface : interfaces) {
System.out.println("- " + iface.getName());
}
// 注解
System.out.println("\n=== 注解 ===");
if (clazz.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation annotation = clazz.getAnnotation(MyAnnotation.class);
System.out.println("MyAnnotation: " + annotation.value());
}
// 字段
System.out.println("\n=== 所有字段(包括私有)===");
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
System.out.println("- " + field.getName() +
": " + field.getType().getSimpleName() +
" [" + Modifier.toString(field.getModifiers()) + "]");
}
// 构造器
System.out.println("\n=== 所有构造器 ===");
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println("- " + constructor.getName() +
" 参数: " + Arrays.toString(
Arrays.stream(constructor.getParameterTypes())
.map(Class::getSimpleName)
.toArray(String[]::new)));
}
// 方法
System.out.println("\n=== 所有方法(包括私有)===");
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
System.out.println("- " + method.getName() +
" 返回: " + method.getReturnType().getSimpleName() +
" 参数: " + Arrays.toString(
Arrays.stream(method.getParameterTypes())
.map(Class::getSimpleName)
.toArray(String[]::new)));
}
}
}
2.3 字段操作
import java.lang.reflect.Field;
/**
* 字段操作示例
*/
class User {
private String username = "default";
private int age = 18;
public String email = "test@example.com";
private static final String VERSION = "1.0";
@Override
public String toString() {
return "User{username='" + username + "', age=" + age +
", email='" + email + "'}";
}
}
public class FieldDemo {
public static void main(String[] args) throws Exception {
User user = new User();
Class<?> clazz = user.getClass();
// 获取公共字段
System.out.println("=== 公共字段 ===");
Field[] publicFields = clazz.getFields();
for (Field field : publicFields) {
System.out.println(field.getName());
}
// 获取所有字段(包括私有)
System.out.println("\n=== 所有字段 ===");
Field[] allFields = clazz.getDeclaredFields();
for (Field field : allFields) {
System.out.println(field.getName() + ": " + field.getType().getSimpleName());
}
// 读取字段值
System.out.println("\n=== 读取字段值 ===");
Field emailField = clazz.getField("email");
Object emailValue = emailField.get(user);
System.out.println("email: " + emailValue);
// 修改字段值
System.out.println("\n=== 修改字段值 ===");
emailField.set(user, "new@example.com");
System.out.println("修改后: " + user);
// 操作私有字段
System.out.println("\n=== 操作私有字段 ===");
Field usernameField = clazz.getDeclaredField("username");
usernameField.setAccessible(true); // 打破访问限制
System.out.println("原始username: " + usernameField.get(user));
usernameField.set(user, "zhangsan");
System.out.println("修改后: " + user);
// 操作静态字段
System.out.println("\n=== 操作静态字段 ===");
Field versionField = clazz.getDeclaredField("VERSION");
versionField.setAccessible(true);
// 静态字段,第一个参数传null
System.out.println("VERSION: " + versionField.get(null));
// 注意:final字段在运行时修改会报错或无效
// 字段类型判断
System.out.println("\n=== 字段类型判断 ===");
Field ageField = clazz.getDeclaredField("age");
System.out.println("isPrimitive: " + ageField.getType().isPrimitive());
System.out.println("isArray: " + ageField.getType().isArray());
}
}
2.4 方法操作
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
/**
* 方法操作示例
*/
class Calculator {
private int result = 0;
public int add(int a, int b) {
return a + b;
}
public int subtract(int a, int b) {
return a - b;
}
private void setResult(int result) {
this.result = result;
}
public static int multiply(int a, int b) {
return a * b;
}
public int sum(int... numbers) {
int total = 0;
for (int num : numbers) {
total += num;
}
return total;
}
public void overloaded(String s) {
System.out.println("String: " + s);
}
public void overloaded(int i) {
System.out.println("int: " + i);
}
}
public class MethodDemo {
public static void main(String[] args) throws Exception {
Calculator calculator = new Calculator();
Class<?> clazz = calculator.getClass();
// 获取所有公共方法(包括继承的)
System.out.println("=== 公共方法 ===");
Method[] publicMethods = clazz.getMethods();
for (Method method : publicMethods) {
if (method.getDeclaringClass() == clazz) { // 只看本类定义的
System.out.println(method.getName());
}
}
// 调用普通方法
System.out.println("\n=== 调用普通方法 ===");
Method addMethod = clazz.getMethod("add", int.class, int.class);
Object result = addMethod.invoke(calculator, 10, 20);
System.out.println("add(10, 20) = " + result);
// 调用私有方法
System.out.println("\n=== 调用私有方法 ===");
Method setResultMethod = clazz.getDeclaredMethod("setResult", int.class);
setResultMethod.setAccessible(true);
setResultMethod.invoke(calculator, 100);
// 调用静态方法
System.out.println("\n=== 调用静态方法 ===");
Method multiplyMethod = clazz.getMethod("multiply", int.class, int.class);
Object staticResult = multiplyMethod.invoke(null, 5, 6); // 静态方法,对象传null
System.out.println("multiply(5, 6) = " + staticResult);
// 调用可变参数方法
System.out.println("\n=== 调用可变参数方法 ===");
Method sumMethod = clazz.getMethod("sum", int[].class);
Object sumResult = sumMethod.invoke(calculator, new Object[]{new int[]{1, 2, 3, 4, 5}});
System.out.println("sum(1,2,3,4,5) = " + sumResult);
// 方法重载处理
System.out.println("\n=== 方法重载 ===");
Method overloadedString = clazz.getMethod("overloaded", String.class);
Method overloadedInt = clazz.getMethod("overloaded", int.class);
overloadedString.invoke(calculator, "hello");
overloadedInt.invoke(calculator, 123);
// 方法参数信息(Java 8+)
System.out.println("\n=== 方法参数信息 ===");
Parameter[] parameters = addMethod.getParameters();
for (Parameter param : parameters) {
System.out.println("参数: " + param.getName() +
", 类型: " + param.getType().getSimpleName());
}
}
}
2.5 构造器与对象创建
import java.lang.reflect.Constructor;
/**
* 构造器操作与对象创建
*/
class Student {
private String name;
private int age;
// 无参构造器
public Student() {
this.name = "Unknown";
this.age = 0;
}
// 有参构造器
public Student(String name) {
this.name = name;
this.age = 18;
}
// 私有构造器
private Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{name='" + name + "', age=" + age + "}";
}
}
public class ConstructorDemo {
public static void main(String[] args) throws Exception {
Class<Student> clazz = Student.class;
// 获取所有公共构造器
System.out.println("=== 公共构造器 ===");
Constructor<?>[] publicConstructors = clazz.getConstructors();
for (Constructor<?> constructor : publicConstructors) {
System.out.println("参数数量: " + constructor.getParameterCount());
}
// 获取所有构造器(包括私有)
System.out.println("\n=== 所有构造器 ===");
Constructor<?>[] allConstructors = clazz.getDeclaredConstructors();
for (Constructor<?> constructor : allConstructors) {
System.out.println("参数: " + constructor.getParameterCount() +
", 修饰符: " + Modifier.toString(constructor.getModifiers()));
}
// 方式1:Class.newInstance()(已废弃,只能调用无参构造器)
System.out.println("\n=== 创建对象方式1(无参)===");
Student student1 = clazz.newInstance();
System.out.println(student1);
// 方式2:Constructor.newInstance()(推荐)
System.out.println("\n=== 创建对象方式2(有参)===");
Constructor<Student> constructor1 = clazz.getConstructor(String.class);
Student student2 = constructor1.newInstance("张三");
System.out.println(student2);
// 调用私有构造器
System.out.println("\n=== 调用私有构造器 ===");
Constructor<Student> privateConstructor =
clazz.getDeclaredConstructor(String.class, int.class);
privateConstructor.setAccessible(true);
Student student3 = privateConstructor.newInstance("李四", 20);
System.out.println(student3);
// 获取构造器参数信息
System.out.println("\n=== 构造器参数信息 ===");
Constructor<Student> twoArgConstructor =
clazz.getDeclaredConstructor(String.class, int.class);
Class<?>[] paramTypes = twoArgConstructor.getParameterTypes();
for (Class<?> paramType : paramTypes) {
System.out.println("参数类型: " + paramType.getSimpleName());
}
}
}
2.6 数组操作
import java.lang.reflect.Array;
/**
* 反射操作数组
*/
public class ArrayDemo {
public static void main(String[] args) {
// 创建数组
System.out.println("=== 创建数组 ===");
// 创建String[5]
Object strArray = Array.newInstance(String.class, 5);
System.out.println("数组类型: " + strArray.getClass().getComponentType());
System.out.println("数组长度: " + Array.getLength(strArray));
// 设置元素
Array.set(strArray, 0, "Hello");
Array.set(strArray, 1, "World");
// 获取元素
System.out.println("元素[0]: " + Array.get(strArray, 0));
System.out.println("元素[1]: " + Array.get(strArray, 1));
// 创建多维数组
System.out.println("\n=== 创建多维数组 ===");
// 创建int[3][4]
Object int2DArray = Array.newInstance(int.class, 3, 4);
System.out.println("类型: " + int2DArray.getClass());
// 操作多维数组
Object firstRow = Array.get(int2DArray, 0);
Array.set(firstRow, 0, 100);
// 类型检查
System.out.println("\n=== 类型检查 ===");
int[] nums = {1, 2, 3};
System.out.println("isArray: " + nums.getClass().isArray());
System.out.println("componentType: " + nums.getClass().getComponentType());
// 转换为数组类型
String[] strArrayCasted = (String[]) strArray;
System.out.println("\n转换后: " + java.util.Arrays.toString(strArrayCasted));
}
}
2.7 动态代理
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 动态代理示例
*/
// 接口
interface UserService {
void addUser(String name);
void deleteUser(String name);
String getUser(String name);
}
// 真实实现
class UserServiceImpl implements UserService {
@Override
public void addUser(String name) {
System.out.println("添加用户: " + name);
}
@Override
public void deleteUser(String name) {
System.out.println("删除用户: " + name);
}
@Override
public String getUser(String name) {
System.out.println("查询用户: " + name);
return "User-" + name;
}
}
// 调用处理器
class LogInvocationHandler implements InvocationHandler {
private Object target;
public LogInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 前置处理
System.out.println("[LOG] 调用方法: " + method.getName());
System.out.println("[LOG] 参数: " + java.util.Arrays.toString(args));
long start = System.currentTimeMillis();
// 调用真实方法
Object result = method.invoke(target, args);
long end = System.currentTimeMillis();
// 后置处理
System.out.println("[LOG] 返回值: " + result);
System.out.println("[LOG] 耗时: " + (end - start) + "ms");
return result;
}
}
public class ProxyDemo {
public static void main(String[] args) {
// 真实对象
UserService realService = new UserServiceImpl();
// 创建代理对象
UserService proxyService = (UserService) Proxy.newProxyInstance(
realService.getClass().getClassLoader(),
realService.getClass().getInterfaces(),
new LogInvocationHandler(realService)
);
// 通过代理调用方法
System.out.println("=== 调用代理方法 ===");
proxyService.addUser("张三");
System.out.println();
String user = proxyService.getUser("李四");
System.out.println("\n获取到的用户: " + user);
// 查看代理类信息
System.out.println("\n=== 代理类信息 ===");
System.out.println("是否为代理类: " + Proxy.isProxyClass(proxyService.getClass()));
System.out.println("代理类名: " + proxyService.getClass().getName());
}
}
三、可运行Java代码示例
完整示例:通用Bean工具类
import java.lang.reflect.*;
import java.util.*;
/**
* 通用Bean工具类
*/
public class BeanUtils {
/**
* 复制属性(浅拷贝)
*/
public static <T> T copyProperties(Object source, Class<T> targetClass) {
try {
T target = targetClass.getDeclaredConstructor().newInstance();
copyProperties(source, target);
return target;
} catch (Exception e) {
throw new RuntimeException("复制属性失败", e);
}
}
/**
* 复制属性到目标对象
*/
public static void copyProperties(Object source, Object target) {
Class<?> sourceClass = source.getClass();
Class<?> targetClass = target.getClass();
for (Field sourceField : sourceClass.getDeclaredFields()) {
try {
sourceField.setAccessible(true);
Object value = sourceField.get(source);
Field targetField;
try {
targetField = targetClass.getDeclaredField(sourceField.getName());
} catch (NoSuchFieldException e) {
continue; // 目标类没有该字段,跳过
}
if (targetField.getType().isAssignableFrom(sourceField.getType())) {
targetField.setAccessible(true);
targetField.set(target, value);
}
} catch (Exception e) {
// 忽略单个字段的复制错误
}
}
}
/**
* 对象转Map
*/
public static Map<String, Object> toMap(Object obj) {
Map<String, Object> map = new HashMap<>();
Class<?> clazz = obj.getClass();
for (Field field : clazz.getDeclaredFields()) {
try {
field.setAccessible(true);
map.put(field.getName(), field.get(obj));
} catch (Exception e) {
// 忽略
}
}
return map;
}
/**
* Map转对象
*/
public static <T> T fromMap(Map<String, Object> map, Class<T> clazz) {
try {
T obj = clazz.getDeclaredConstructor().newInstance();
for (Map.Entry<String, Object> entry : map.entrySet()) {
try {
Field field = clazz.getDeclaredField(entry.getKey());
field.setAccessible(true);
Object value = entry.getValue();
if (value != null && !field.getType().isAssignableFrom(value.getClass())) {
// 简单类型转换
value = convertValue(value, field.getType());
}
field.set(obj, value);
} catch (NoSuchFieldException e) {
// 忽略不存在的字段
}
}
return obj;
} catch (Exception e) {
throw new RuntimeException("Map转对象失败", e);
}
}
/**
* 简单类型转换
*/
private static Object convertValue(Object value, Class<?> targetType) {
String strValue = value.toString();
if (targetType == String.class) return strValue;
if (targetType == int.class || targetType == Integer.class) return Integer.parseInt(strValue);
if (targetType == long.class || targetType == Long.class) return Long.parseLong(strValue);
if (targetType == double.class || targetType == Double.class) return Double.parseDouble(strValue);
if (targetType == boolean.class || targetType == Boolean.class) return Boolean.parseBoolean(strValue);
return value;
}
/**
* 获取字段值(支持嵌套路径)
*/
public static Object getFieldValue(Object obj, String fieldPath) {
String[] fields = fieldPath.split("\\.");
Object current = obj;
for (String fieldName : fields) {
if (current == null) return null;
try {
Field field = current.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
current = field.get(current);
} catch (Exception e) {
throw new RuntimeException("获取字段值失败: " + fieldName, e);
}
}
return current;
}
/**
* 设置字段值(支持嵌套路径)
*/
public static void setFieldValue(Object obj, String fieldPath, Object value) {
String[] fields = fieldPath.split("\\.");
Object current = obj;
// 找到最后一个字段的父对象
for (int i = 0; i < fields.length - 1; i++) {
try {
Field field = current.getClass().getDeclaredField(fields[i]);
field.setAccessible(true);
current = field.get(current);
} catch (Exception e) {
throw new RuntimeException("获取字段失败: " + fields[i], e);
}
}
// 设置最后一个字段的值
try {
Field field = current.getClass().getDeclaredField(fields[fields.length - 1]);
field.setAccessible(true);
field.set(current, value);
} catch (Exception e) {
throw new RuntimeException("设置字段值失败: " + fieldPath, e);
}
}
/**
* 调用getter方法
*/
public static Object invokeGetter(Object obj, String propertyName) {
String getterName = "get" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
try {
Method getter = obj.getClass().getMethod(getterName);
return getter.invoke(obj);
} catch (Exception e) {
throw new RuntimeException("调用getter失败: " + getterName, e);
}
}
/**
* 调用setter方法
*/
public static void invokeSetter(Object obj, String propertyName, Object value) {
String setterName = "set" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
try {
Method setter = obj.getClass().getMethod(setterName, value.getClass());
setter.invoke(obj, value);
} catch (Exception e) {
throw new RuntimeException("调用setter失败: " + setterName, e);
}
}
}
// === 测试实体类 ===
class Person {
private String name;
private int age;
private Address address;
public Person() {}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// getter/setter
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public Address getAddress() { return address; }
public void setAddress(Address address) { this.address = address; }
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + ", address=" + address + "}";
}
}
class Address {
private String city;
private String street;
public Address() {}
public Address(String city, String street) {
this.city = city;
this.street = street;
}
public String getCity() { return city; }
public void setCity(String city) { this.city = city; }
public String getStreet() { return street; }
public void setStreet(String street) { this.street = street; }
@Override
public String toString() {
return "Address{city='" + city + "', street='" + street + "'}";
}
}
// === 测试 ===
class BeanUtilsDemo {
public static void main(String[] args) {
// 对象转Map
Person person = new Person("张三", 25);
person.setAddress(new Address("北京", "朝阳路"));
System.out.println("=== 对象转Map ===");
Map<String, Object> map = BeanUtils.toMap(person);
System.out.println(map);
// Map转对象
System.out.println("\n=== Map转对象 ===");
Map<String, Object> newMap = new HashMap<>();
newMap.put("name", "李四");
newMap.put("age", 30);
Person newPerson = BeanUtils.fromMap(newMap, Person.class);
System.out.println(newPerson);
// 嵌套路径获取
System.out.println("\n=== 嵌套路径获取 ===");
Object city = BeanUtils.getFieldValue(person, "address.city");
System.out.println("address.city: " + city);
// getter/setter
System.out.println("\n=== getter/setter ===");
String name = (String) BeanUtils.invokeGetter(person, "name");
System.out.println("getName(): " + name);
BeanUtils.invokeSetter(person, "name", "王五");
System.out.println("setName后: " + person.getName());
}
}
完整示例:简易ORM框架
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.sql.*;
import java.util.*;
// === 注解定义 ===
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface Table {
String name() default "";
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@interface Id {
String column() default "";
boolean autoIncrement() default true;
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@interface Column {
String name() default "";
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@interface Ignore {}
// === ORM核心 ===
class SimpleORM {
/**
* 插入对象
*/
public static <T> String generateInsert(T entity) {
Class<?> clazz = entity.getClass();
String tableName = getTableName(clazz);
List<String> columns = new ArrayList<>();
List<String> values = new ArrayList<>();
for (Field field : clazz.getDeclaredFields()) {
if (field.isAnnotationPresent(Ignore.class)) continue;
field.setAccessible(true);
Object value;
try {
value = field.get(entity);
} catch (IllegalAccessException e) {
continue;
}
// 跳过null值和自增主键
if (value == null) continue;
if (field.isAnnotationPresent(Id.class) &&
field.getAnnotation(Id.class).autoIncrement()) {
continue;
}
String columnName = getColumnName(field);
columns.add(columnName);
values.add(formatValue(value));
}
return String.format("INSERT INTO %s (%s) VALUES (%s)",
tableName,
String.join(", ", columns),
String.join(", ", values));
}
/**
* 根据ID查询
*/
public static <T> String generateSelectById(Class<T> clazz, Object id) {
String tableName = getTableName(clazz);
Field idField = getIdField(clazz);
String idColumn = idField.isAnnotationPresent(Id.class) ?
idField.getAnnotation(Id.class).column() : idField.getName();
if (idColumn.isEmpty()) idColumn = idField.getName();
return String.format("SELECT * FROM %s WHERE %s = %s",
tableName, idColumn, formatValue(id));
}
/**
* 更新对象
*/
public static <T> String generateUpdate(T entity) {
Class<?> clazz = entity.getClass();
String tableName = getTableName(clazz);
List<String> sets = new ArrayList<>();
String idCondition = null;
for (Field field : clazz.getDeclaredFields()) {
if (field.isAnnotationPresent(Ignore.class)) continue;
field.setAccessible(true);
Object value;
try {
value = field.get(entity);
} catch (IllegalAccessException e) {
continue;
}
String columnName = getColumnName(field);
if (field.isAnnotationPresent(Id.class)) {
idCondition = columnName + " = " + formatValue(value);
} else if (value != null) {
sets.add(columnName + " = " + formatValue(value));
}
}
if (idCondition == null) {
throw new RuntimeException("实体类缺少@Id注解字段");
}
return String.format("UPDATE %s SET %s WHERE %s",
tableName,
String.join(", ", sets),
idCondition);
}
/**
* 删除
*/
public static <T> String generateDelete(Class<T> clazz, Object id) {
String tableName = getTableName(clazz);
Field idField = getIdField(clazz);
String idColumn = getColumnName(idField);
return String.format("DELETE FROM %s WHERE %s = %s",
tableName, idColumn, formatValue(id));
}
/**
* 结果集转对象
*/
public static <T> T mapResultSet(ResultSet rs, Class<T> clazz) {
try {
T obj = clazz.getDeclaredConstructor().newInstance();
ResultSetMetaData metaData = rs.getMetaData();
int columnCount = metaData.getColumnCount();
Map<String, Field> fieldMap = new HashMap<>();
for (Field field : clazz.getDeclaredFields()) {
field.setAccessible(true);
fieldMap.put(getColumnName(field).toLowerCase(), field);
fieldMap.put(field.getName().toLowerCase(), field);
}
for (int i = 1; i <= columnCount; i++) {
String columnName = metaData.getColumnLabel(i).toLowerCase();
Field field = fieldMap.get(columnName);
if (field != null) {
Object value = rs.getObject(i);
field.set(obj, value);
}
}
return obj;
} catch (Exception e) {
throw new RuntimeException("映射结果集失败", e);
}
}
// === 辅助方法 ===
private static String getTableName(Class<?> clazz) {
if (clazz.isAnnotationPresent(Table.class)) {
String name = clazz.getAnnotation(Table.class).name();
if (!name.isEmpty()) return name;
}
// 驼峰转下划线
return camelToSnake(clazz.getSimpleName());
}
private static String getColumnName(Field field) {
if (field.isAnnotationPresent(Id.class)) {
String name = field.getAnnotation(Id.class).column();
if (!name.isEmpty()) return name;
}
if (field.isAnnotationPresent(Column.class)) {
String name = field.getAnnotation(Column.class).name();
if (!name.isEmpty()) return name;
}
return camelToSnake(field.getName());
}
private static Field getIdField(Class<?> clazz) {
for (Field field : clazz.getDeclaredFields()) {
if (field.isAnnotationPresent(Id.class)) {
return field;
}
}
throw new RuntimeException("实体类缺少@Id注解字段");
}
private static String formatValue(Object value) {
if (value instanceof String || value instanceof java.util.Date) {
return "'" + value + "'";
}
return value.toString();
}
private static String camelToSnake(String str) {
return str.replaceAll("([a-z])([A-Z])", "$1_$2").toLowerCase();
}
}
// === 测试实体 ===
@Table(name = "t_user")
class User {
@Id(column = "id")
private Long id;
@Column(name = "username")
private String username;
private String password;
private Integer age;
@Ignore
private String confirmPassword;
// getter/setter省略
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
public Integer getAge() { return age; }
public void setAge(Integer age) { this.age = age; }
public String getConfirmPassword() { return confirmPassword; }
public void setConfirmPassword(String confirmPassword) { this.confirmPassword = confirmPassword; }
}
// === 测试 ===
class ORMDemo {
public static void main(String[] args) {
// 插入
User user = new User();
user.setId(1L);
user.setUsername("zhangsan");
user.setPassword("123456");
user.setAge(25);
user.setConfirmPassword("123456"); // 会被忽略
System.out.println("=== INSERT ===");
System.out.println(SimpleORM.generateInsert(user));
System.out.println("\n=== SELECT BY ID ===");
System.out.println(SimpleORM.generateSelectById(User.class, 1L));
System.out.println("\n=== UPDATE ===");
user.setAge(26);
System.out.println(SimpleORM.generateUpdate(user));
System.out.println("\n=== DELETE ===");
System.out.println(SimpleORM.generateDelete(User.class, 1L));
}
}
四、实战应用场景
场景1:注解驱动的依赖注入
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
// === 注解定义 ===
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface Component {
String value() default "";
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@interface Autowired {
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@interface Qualifier {
String value();
}
// === 简易IoC容器 ===
class SimpleContainer {
private static final Map<String, Object> beans = new ConcurrentHashMap<>();
private static final Map<Class<?>, String> typeToName = new ConcurrentHashMap<>();
/**
* 注册Bean
*/
public static void registerBean(String name, Object bean) {
beans.put(name, bean);
typeToName.put(bean.getClass(), name);
}
/**
* 获取Bean
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) {
return (T) beans.get(name);
}
public static <T> T getBean(Class<T> clazz) {
String name = typeToName.get(clazz);
if (name == null) {
// 尝试查找实现类
for (Object bean : beans.values()) {
if (clazz.isInstance(bean)) {
return (T) bean;
}
}
}
return name != null ? (T) beans.get(name) : null;
}
/**
* 扫描并注册组件
*/
public static void scan(String basePackage) throws Exception {
// 模拟扫描(实际应扫描类路径)
Class<?>[] classes = {UserService.class, OrderService.class, UserController.class};
for (Class<?> clazz : classes) {
if (clazz.isAnnotationPresent(Component.class)) {
String beanName = clazz.getAnnotation(Component.class).value();
if (beanName.isEmpty()) {
beanName = clazz.getSimpleName();
beanName = beanName.substring(0, 1).toLowerCase() + beanName.substring(1);
}
Object instance = clazz.getDeclaredConstructor().newInstance();
registerBean(beanName, instance);
}
}
// 依赖注入
for (Object bean : beans.values()) {
injectDependencies(bean);
}
}
/**
* 依赖注入
*/
private static void injectDependencies(Object bean) throws Exception {
Class<?> clazz = bean.getClass();
for (Field field : clazz.getDeclaredFields()) {
if (field.isAnnotationPresent(Autowired.class)) {
field.setAccessible(true);
Object dependency;
if (field.isAnnotationPresent(Qualifier.class)) {
String beanName = field.getAnnotation(Qualifier.class).value();
dependency = getBean(beanName);
} else {
dependency = getBean(field.getType());
}
if (dependency != null) {
field.set(bean, dependency);
}
}
}
}
}
// === 示例组件 ===
@Component
interface UserService {
String getUserName(Long id);
}
@Component("userService")
class UserServiceImpl implements UserService {
@Override
public String getUserName(Long id) {
return "User-" + id;
}
}
@Component
class OrderService {
@Autowired
private UserService userService;
public String getOrderInfo(Long orderId) {
return "Order-" + orderId + ", User: " + userService.getUserName(1L);
}
}
@Component
class UserController {
@Autowired
@Qualifier("userService")
private UserService userService;
@Autowired
private OrderService orderService;
public void showInfo() {
System.out.println("User: " + userService.getUserName(1L));
System.out.println("Order: " + orderService.getOrderInfo(100L));
}
}
// === 测试 ===
class DIDemo {
public static void main(String[] args) throws Exception {
SimpleContainer.scan("com.example");
UserController controller = SimpleContainer.getBean(UserController.class);
controller.showInfo();
}
}
场景2:动态方法调用器
import java.lang.reflect.*;
import java.util.*;
/**
* 动态方法调用器
*/
class MethodInvoker {
private final Object target;
private final Map<String, Method> methodCache = new HashMap<>();
public MethodInvoker(Object target) {
this.target = target;
// 缓存所有方法
for (Method method : target.getClass().getDeclaredMethods()) {
methodCache.put(method.getName(), method);
}
}
/**
* 调用方法(自动类型转换)
*/
public Object invoke(String methodName, Object... args) {
Method method = methodCache.get(methodName);
if (method == null) {
throw new IllegalArgumentException("方法不存在: " + methodName);
}
try {
// 参数类型转换
Object[] convertedArgs = convertArgs(method, args);
method.setAccessible(true);
return method.invoke(target, convertedArgs);
} catch (Exception e) {
throw new RuntimeException("调用方法失败: " + methodName, e);
}
}
/**
* 参数类型转换
*/
private Object[] convertArgs(Method method, Object[] args) {
Parameter[] parameters = method.getParameters();
if (parameters.length == 0 && args == null) return new Object[0];
if (parameters.length == 0) return new Object[0];
if (args == null) return new Object[parameters.length];
Object[] result = new Object[parameters.length];
for (int i = 0; i < parameters.length; i++) {
if (i < args.length && args[i] != null) {
result[i] = convertType(args[i], parameters[i].getType());
}
}
return result;
}
private Object convertType(Object value, Class<?> targetType) {
if (targetType.isInstance(value)) return value;
String strValue = value.toString();
if (targetType == int.class || targetType == Integer.class) return Integer.parseInt(strValue);
if (targetType == long.class || targetType == Long.class) return Long.parseLong(strValue);
if (targetType == double.class || targetType == Double.class) return Double.parseDouble(strValue);
if (targetType == float.class || targetType == Float.class) return Float.parseFloat(strValue);
if (targetType == boolean.class || targetType == Boolean.class) return Boolean.parseBoolean(strValue);
if (targetType == String.class) return strValue;
return value;
}
/**
* 获取所有方法名
*/
public List<String> listMethods() {
return new ArrayList<>(methodCache.keySet());
}
/**
* 获取方法信息
*/
public String getMethodInfo(String methodName) {
Method method = methodCache.get(methodName);
if (method == null) return null;
StringBuilder sb = new StringBuilder();
sb.append(method.getReturnType().getSimpleName())
.append(" ").append(method.getName()).append("(");
Parameter[] params = method.getParameters();
for (int i = 0; i < params.length; i++) {
if (i > 0) sb.append(", ");
sb.append(params[i].getType().getSimpleName())
.append(" ").append(params[i].getName());
}
sb.append(")");
return sb.toString();
}
}
// === 测试 ===
class Calculator {
public int add(int a, int b) { return a + b; }
public double divide(double a, double b) { return a / b; }
public String concat(String a, String b) { return a + b; }
public void print(String msg) { System.out.println("Message: " + msg); }
}
class MethodInvokerDemo {
public static void main(String[] args) {
Calculator calc = new Calculator();
MethodInvoker invoker = new MethodInvoker(calc);
// 列出方法
System.out.println("=== 所有方法 ===");
invoker.listMethods().forEach(m ->
System.out.println(invoker.getMethodInfo(m)));
// 动态调用(自动类型转换)
System.out.println("\n=== 动态调用 ===");
// 字符串参数自动转int
Object result1 = invoker.invoke("add", "10", "20");
System.out.println("add('10', '20') = " + result1);
Object result2 = invoker.invoke("divide", 10, 4);
System.out.println("divide(10, 4) = " + result2);
Object result3 = invoker.invoke("concat", "Hello", "World");
System.out.println("concat('Hello', 'World') = " + result3);
invoker.invoke("print", "动态调用成功");
}
}
五、总结与最佳实践
核心要点回顾
| 功能 | 关键类/方法 |
|---|---|
| 获取Class | 类名.class、对象.getClass()、Class.forName() |
| 类信息 | getName()、getModifiers()、getSuperclass()、getInterfaces() |
| 字段操作 | getField()、getDeclaredField()、setAccessible() |
| 方法操作 | getMethod()、getDeclaredMethod()、invoke() |
| 对象创建 | newInstance()、Constructor.newInstance() |
| 动态代理 | Proxy.newProxyInstance()、InvocationHandler |
最佳实践
-
缓存反射结果
// 缓存Method对象,避免重复查找 private static final Map<String, Method> METHOD_CACHE = new ConcurrentHashMap<>(); public static Method getMethod(Class<?> clazz, String name, Class<?>... paramTypes) { String key = clazz.getName() + "#" + name; return METHOD_CACHE.computeIfAbsent(key, k -> { try { return clazz.getMethod(name, paramTypes); } catch (NoSuchMethodException e) { return null; } }); } -
使用setAccessible要谨慎
// 只在必要时使用,访问后考虑恢复 Field field = clazz.getDeclaredField("name"); boolean wasAccessible = field.isAccessible(); field.setAccessible(true); try { // 操作字段 } finally { field.setAccessible(wasAccessible); } -
异常处理要完整
try { Method method = clazz.getMethod("doSomething"); method.invoke(obj); } catch (NoSuchMethodException e) { // 方法不存在 } catch (IllegalAccessException e) { // 访问权限问题 } catch (InvocationTargetException e) { // 方法执行抛出异常 Throwable cause = e.getCause(); // 获取真实异常 } -
性能优化建议
- 缓存反射结果
- 减少反射调用次数
- 高频场景考虑代码生成(如ASM、CGLIB)
- 使用MethodHandle(Java 7+)
-
安全注意事项
- 敏感操作前检查权限
- 避免暴露内部实现细节
- 使用SecurityManager控制反射权限
反射 vs MethodHandle
import java.lang.invoke.*;
/**
* MethodHandle示例(Java 7+,性能更好)
*/
public class MethodHandleDemo {
public static void main(String[] args) throws Throwable {
String str = "Hello";
// 反射方式
Method method = String.class.getMethod("substring", int.class, int.class);
String result1 = (String) method.invoke(str, 0, 3);
System.out.println("反射: " + result1);
// MethodHandle方式(更快)
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodType methodType = MethodType.methodType(String.class, int.class, int.class);
MethodHandle handle = lookup.findVirtual(String.class, "substring", methodType);
String result2 = (String) handle.invoke(str, 0, 3);
System.out.println("MethodHandle: " + result2);
}
}
常见问题
-
为什么反射慢?
- 需要查找元数据
- 需要检查访问权限
- 需要创建参数数组
- JIT优化受限
-
如何选择?
- 框架开发:反射更灵活
- 高性能场景:MethodHandle或代码生成
- 简单场景:直接调用
扩展阅读
- Java反射API文档:java.lang.reflect包
- MethodHandle:java.lang.invoke包
- ASM库:字节码操作框架
- CGLIB:动态代理增强库