Java反射机制详解
Java反射机制详解
什么是反射
反射是Java在运行时动态获取类信息、创建对象、调用方法和访问字段的能力。它是框架设计的基石。
获取Class对象
public class ReflectionDemo {
public static void main(String[] args) throws ClassNotFoundException {
// 方式1:Class.forName()
Class<?> clazz1 = Class.forName("java.lang.String");
// 方式2:.class语法
Class<String> clazz2 = String.class;
// 方式3:getClass()
String str = "hello";
Class<?> clazz3 = str.getClass();
// 三种方式获取的是同一个Class对象
System.out.println(clazz1 == clazz2); // true
System.out.println(clazz2 == clazz3); // true
}
}
反射创建对象
public class User {
private String name;
private int age;
public User() {
this.name = "default";
}
public User(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "User{name='" + name + "', age=" + age + "}";
}
}
public class CreateObjectDemo {
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("com.example.User");
// 使用无参构造器
User user1 = (User) clazz.getDeclaredConstructor().newInstance();
System.out.println(user1);
// 使用有参构造器
Constructor<?> constructor = clazz.getDeclaredConstructor(String.class, int.class);
User user2 = (User) constructor.newInstance("张三", 25);
System.out.println(user2);
}
}
反射访问字段
public class FieldDemo {
public static void main(String[] args) throws Exception {
User user = new User("张三", 25);
Class<?> clazz = user.getClass();
// 获取所有字段(包括private)
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
System.out.println(field.getName() + ": " + field.getType());
}
// 获取指定字段
Field nameField = clazz.getDeclaredField("name");
// 设置可访问(访问private字段)
nameField.setAccessible(true);
// 读取字段值
String name = (String) nameField.get(user);
System.out.println("name = " + name);
// 设置字段值
nameField.set(user, "李四");
System.out.println("修改后: " + user);
// 修改static字段
Field staticField = clazz.getDeclaredField("COUNT");
staticField.setAccessible(true);
staticField.set(null, 100);
}
}
反射调用方法
public class Calculator {
public int add(int a, int b) {
return a + b;
}
private int multiply(int a, int b) {
return a * b;
}
public static String format(String pattern, Object... args) {
return String.format(pattern, args);
}
}
public class MethodDemo {
public static void main(String[] args) throws Exception {
Calculator calc = new Calculator();
Class<?> clazz = calc.getClass();
// 获取所有方法
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method.getName());
}
// 调用public方法
Method addMethod = clazz.getDeclaredMethod("add", int.class, int.class);
int result = (int) addMethod.invoke(calc, 10, 20);
System.out.println("10 + 20 = " + result);
// 调用private方法
Method multiplyMethod = clazz.getDeclaredMethod("multiply", int.class, int.class);
multiplyMethod.setAccessible(true);
int product = (int) multiplyMethod.invoke(calc, 10, 20);
System.out.println("10 × 20 = " + product);
// 调用static方法
Method formatMethod = clazz.getDeclaredMethod("format", String.class, Object[].class);
String formatted = (String) formatMethod.invoke(null, "Hello %s", new Object[]{"World"});
System.out.println(formatted);
}
}
反射获取注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TableName {
String value();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
String value() default "";
boolean nullable() default true;
}
@TableName("users")
public class User {
@Column(value = "user_name", nullable = false)
private String name;
@Column("user_age")
private int age;
}
public class AnnotationDemo {
public static void main(String[] args) {
Class<?> clazz = User.class;
// 获取类注解
TableName tableName = clazz.getAnnotation(TableName.class);
System.out.println("表名: " + tableName.value());
// 获取字段注解
for (Field field : clazz.getDeclaredFields()) {
Column column = field.getAnnotation(Column.class);
if (column != null) {
System.out.println(field.getName() + " -> " +
column.value() + ", nullable=" + column.nullable());
}
}
}
}
反射实现简易ORM框架
public class SimpleORM {
public static <T> T findById(Connection conn, Class<T> clazz, Object id) throws Exception {
TableName table = clazz.getAnnotation(TableName.class);
if (table == null) throw new RuntimeException("缺少@TableName注解");
String sql = "SELECT * FROM " + table.value() + " WHERE id = ?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setObject(1, id);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
T obj = clazz.getDeclaredConstructor().newInstance();
for (Field field : clazz.getDeclaredFields()) {
Column column = field.getAnnotation(Column.class);
String columnName = column != null ? column.value() : field.getName();
field.setAccessible(true);
field.set(obj, rs.getObject(columnName));
}
return obj;
}
return null;
}
}
性能优化
public class ReflectionPerformance {
// 缓存Method/Field/Constructor
private static final Map<String, Method> methodCache = new ConcurrentHashMap<>();
public static Method getMethod(Class<?> clazz, String name, Class<?>... paramTypes)
throws NoSuchMethodException {
String key = clazz.getName() + "." + name;
return methodCache.computeIfAbsent(key, k -> {
try {
return clazz.getDeclaredMethod(name, paramTypes);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
});
}
// 使用MethodHandle替代反射(Java 7+)
private static final MethodHandles.Lookup lookup = MethodHandles.lookup();
public static void methodHandleDemo() throws Throwable {
MethodType type = MethodType.methodType(String.class, int.class);
MethodHandle handle = lookup.findVirtual(String.class, "substring", type);
String result = (String) handle.invoke("Hello World", 6);
System.out.println(result); // World
}
}
总结
反射是Java动态性的核心,但使用时要注意性能开销。建议在框架中使用反射,业务代码中谨慎使用。