Java反射详解
一、反射基础概念
1.1 什么是反射?
反射(Reflection)是Java语言的一种特性,允许程序在运行时获取类的内部信息,并能直接操作类的属性、方法和构造函数。
通俗理解:就像给Java程序装了一面"镜子",可以照出类的所有内部结构,即使这些结构在编译时是私有的或不可见的。
1.2 反射的核心类
Class- 代表类的实体Field- 代表类的成员变量Method- 代表类的方法Constructor- 代表类的构造方法
二、获取Class对象的三种方式
public class ClassObjectExample {
public static void main(String[] args) throws Exception {
// 方式1:通过类名.class
Class<String> stringClass = String.class;
System.out.println("方式1: " + stringClass.getName());
// 方式2:通过对象.getClass()
String str = "Hello";
Class<?> strClass = str.getClass();
System.out.println("方式2: " + strClass.getName());
// 方式3:通过Class.forName()
Class<?> forNameClass = Class.forName("java.lang.String");
System.out.println("方式3: " + forNameClass.getName());
// 验证三个Class对象是否相同
System.out.println("是否相同: " + (stringClass == strClass && strClass == forNameClass));
}
}
三、反射操作构造函数
import java.lang.reflect.Constructor;
public class ConstructorExample {
static class User {
private String name;
private int age;
public User() {
this.name = "默认用户";
this.age = 18;
}
public User(String name) {
this.name = name;
this.age = 20;
}
private User(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "User{name='" + name + "', age=" + age + "}";
}
}
public static void main(String[] args) throws Exception {
Class<User> userClass = User.class;
// 1. 获取所有公有构造方法
System.out.println("=== 公有构造方法 ===");
Constructor<?>[] publicConstructors = userClass.getConstructors();
for (Constructor<?> constructor : publicConstructors) {
System.out.println(constructor);
}
// 2. 获取所有构造方法(包括私有)
System.out.println("\n=== 所有构造方法 ===");
Constructor<?>[] allConstructors = userClass.getDeclaredConstructors();
for (Constructor<?> constructor : allConstructors) {
System.out.println(constructor);
}
// 3. 调用无参构造创建对象
System.out.println("\n=== 调用无参构造 ===");
Constructor<User> noArgConstructor = userClass.getConstructor();
User user1 = noArgConstructor.newInstance();
System.out.println(user1);
// 4. 调用有参构造创建对象
System.out.println("\n=== 调用有参构造 ===");
Constructor<User> oneArgConstructor = userClass.getConstructor(String.class);
User user2 = oneArgConstructor.newInstance("张三");
System.out.println(user2);
// 5. 调用私有构造方法
System.out.println("\n=== 调用私有构造 ===");
Constructor<User> privateConstructor = userClass.getDeclaredConstructor(String.class, int.class);
privateConstructor.setAccessible(true); // 设置可访问私有方法
User user3 = privateConstructor.newInstance("李四", 25);
System.out.println(user3);
}
}
四、反射操作字段(Field)
import java.lang.reflect.Field;
public class FieldExample {
static class Student {
public String publicField = "公有字段";
protected String protectedField = "受保护字段";
private String privateField = "私有字段";
String defaultField = "默认字段";
}
public static void main(String[] args) throws Exception {
Class<Student> studentClass = Student.class;
Student student = studentClass.newInstance();
// 1. 获取所有公有字段
System.out.println("=== 公有字段 ===");
Field[] publicFields = studentClass.getFields();
for (Field field : publicFields) {
System.out.println(field.getName() + ": " + field.get(student));
}
// 2. 获取所有字段(包括私有)
System.out.println("\n=== 所有字段 ===");
Field[] allFields = studentClass.getDeclaredFields();
for (Field field : allFields) {
field.setAccessible(true); // 设置可访问私有字段
System.out.println(field.getName() + ": " + field.get(student));
}
// 3. 获取特定字段并修改值
System.out.println("\n=== 修改字段值 ===");
Field privateField = studentClass.getDeclaredField("privateField");
privateField.setAccessible(true);
System.out.println("修改前: " + privateField.get(student));
privateField.set(student, "修改后的私有字段");
System.out.println("修改后: " + privateField.get(student));
// 4. 获取和修改静态字段
System.out.println("\n=== 静态字段操作 ===");
Field staticField = FieldExample.class.getDeclaredField("STATIC_FIELD");
System.out.println("静态字段: " + staticField.get(null));
staticField.set(null, "修改后的静态字段");
System.out.println("修改后: " + staticField.get(null));
}
public static String STATIC_FIELD = "原始静态字段";
}
五、反射操作方法(Method)
import java.lang.reflect.Method;
public class MethodExample {
static class Calculator {
public int add(int a, int b) {
return a + b;
}
protected int multiply(int a, int b) {
return a * b;
}
private int subtract(int a, int b) {
return a - b;
}
public static void staticMethod() {
System.out.println("这是一个静态方法");
}
private void printMessage(String message) {
System.out.println("消息: " + message);
}
}
public static void main(String[] args) throws Exception {
Class<Calculator> calculatorClass = Calculator.class;
Calculator calculator = calculatorClass.newInstance();
// 1. 获取所有公有方法(包括继承的)
System.out.println("=== 公有方法 ===");
Method[] publicMethods = calculatorClass.getMethods();
for (Method method : publicMethods) {
System.out.println(method.getName());
}
// 2. 获取本类所有方法(包括私有)
System.out.println("\n=== 本类所有方法 ===");
Method[] allMethods = calculatorClass.getDeclaredMethods();
for (Method method : allMethods) {
System.out.println(method.getName());
}
// 3. 调用公有方法
System.out.println("\n=== 调用公有方法 ===");
Method addMethod = calculatorClass.getMethod("add", int.class, int.class);
int result = (int) addMethod.invoke(calculator, 10, 20);
System.out.println("10 + 20 = " + result);
// 4. 调用私有方法
System.out.println("\n=== 调用私有方法 ===");
Method subtractMethod = calculatorClass.getDeclaredMethod("subtract", int.class, int.class);
subtractMethod.setAccessible(true);
int subtractResult = (int) subtractMethod.invoke(calculator, 20, 10);
System.out.println("20 - 10 = " + subtractResult);
// 5. 调用静态方法
System.out.println("\n=== 调用静态方法 ===");
Method staticMethod = calculatorClass.getDeclaredMethod("staticMethod");
staticMethod.invoke(null);
// 6. 调用带参数的方法
System.out.println("\n=== 调用带参方法 ===");
Method printMethod = calculatorClass.getDeclaredMethod("printMessage", String.class);
printMethod.setAccessible(true);
printMethod.invoke(calculator, "Hello Reflection!");
}
}
六、反射操作数组
import java.lang.reflect.Array;
public class ArrayReflectionExample {
public static void main(String[] args) throws Exception {
// 1. 创建数组
System.out.println("=== 创建数组 ===");
int[] intArray = (int[]) Array.newInstance(int.class, 5);
System.out.println("数组长度: " + Array.getLength(intArray));
// 2. 设置数组元素
System.out.println("\n=== 设置数组元素 ===");
for (int i = 0; i < Array.getLength(intArray); i++) {
Array.set(intArray, i, i * 10);
}
// 3. 获取数组元素
System.out.println("\n=== 获取数组元素 ===");
for (int i = 0; i < Array.getLength(intArray); i++) {
System.out.println("intArray[" + i + "] = " + Array.get(intArray, i));
}
// 4. 创建多维数组
System.out.println("\n=== 多维数组 ===");
int[][] twoDArray = (int[][]) Array.newInstance(int.class, 3, 4);
// 设置多维数组值
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
Array.set(Array.get(twoDArray, i), j, i * 10 + j);
}
}
// 读取多维数组值
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
System.out.print(Array.get(Array.get(twoDArray, i), j) + "\t");
}
System.out.println();
}
}
}
七、反射操作注解
import java.lang.annotation.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
// 定义注解
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
String value() default "";
String description() default "";
}
// 使用注解的类
@MyAnnotation(value = "类注解", description = "这是一个测试类")
class AnnotatedClass {
@MyAnnotation(value = "字段注解", description = "用户名字段")
private String username;
@MyAnnotation(value = "方法注解", description = "获取用户信息")
public void getUserInfo() {
System.out.println("用户信息");
}
}
public class AnnotationReflectionExample {
public static void main(String[] args) throws Exception {
Class<AnnotatedClass> clazz = AnnotatedClass.class;
// 1. 获取类上的注解
System.out.println("=== 类注解 ===");
if (clazz.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation classAnnotation = clazz.getAnnotation(MyAnnotation.class);
System.out.println("值: " + classAnnotation.value());
System.out.println("描述: " + classAnnotation.description());
}
// 2. 获取字段上的注解
System.out.println("\n=== 字段注解 ===");
Field field = clazz.getDeclaredField("username");
if (field.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation fieldAnnotation = field.getAnnotation(MyAnnotation.class);
System.out.println("值: " + fieldAnnotation.value());
System.out.println("描述: " + fieldAnnotation.description());
}
// 3. 获取方法上的注解
System.out.println("\n=== 方法注解 ===");
Method method = clazz.getMethod("getUserInfo");
if (method.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation methodAnnotation = method.getAnnotation(MyAnnotation.class);
System.out.println("值: " + methodAnnotation.value());
System.out.println("描述: " + methodAnnotation.description());
}
// 4. 获取所有注解
System.out.println("\n=== 所有注解 ===");
Annotation[] annotations = clazz.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation.annotationType().getSimpleName());
}
}
}
八、实际生产开发中的使用场景
8.1 Spring框架的依赖注入
// 模拟Spring的依赖注入
public class SimpleContainer {
private Map<String, Object> beans = new HashMap<>();
public void register(String name, Object bean) {
beans.put(name, bean);
}
public <T> T getBean(Class<T> clazz) throws Exception {
// 创建实例
T instance = clazz.newInstance();
// 注入依赖(模拟@Autowired)
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (beans.containsKey(field.getName())) {
field.setAccessible(true);
field.set(instance, beans.get(field.getName()));
}
}
return instance;
}
}
// 使用示例
class UserService {
private UserRepository userRepository;
public void saveUser(String user) {
userRepository.save(user);
System.out.println("保存用户: " + user);
}
}
class UserRepository {
public void save(String user) {
System.out.println("数据库保存: " + user);
}
}
public class SpringLikeExample {
public static void main(String[] args) throws Exception {
SimpleContainer container = new SimpleContainer();
container.register("userRepository", new UserRepository());
UserService userService = container.getBean(UserService.class);
userService.saveUser("张三");
}
}
8.2 JSON序列化/反序列化
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
// 简单的JSON序列化工具
public class SimpleJsonSerializer {
// 对象转JSON
public static String toJson(Object obj) throws Exception {
Class<?> clazz = obj.getClass();
Field[] fields = clazz.getDeclaredFields();
StringBuilder json = new StringBuilder();
json.append("{");
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
field.setAccessible(true);
json.append("\"").append(field.getName()).append("\":");
Object value = field.get(obj);
if (value instanceof String) {
json.append("\"").append(value).append("\"");
} else {
json.append(value);
}
if (i < fields.length - 1) {
json.append(",");
}
}
json.append("}");
return json.toString();
}
// JSON转对象
public static <T> T fromJson(String json, Class<T> clazz) throws Exception {
T instance = clazz.newInstance();
// 简单解析JSON(实际生产环境使用成熟的JSON库)
json = json.replace("{", "").replace("}", "");
String[] pairs = json.split(",");
for (String pair : pairs) {
String[] keyValue = pair.split(":");
String key = keyValue[0].replace("\"", "").trim();
String value = keyValue[1].replace("\"", "").trim();
Field field = clazz.getDeclaredField(key);
field.setAccessible(true);
// 类型转换(简化版)
if (field.getType() == int.class) {
field.set(instance, Integer.parseInt(value));
} else if (field.getType() == String.class) {
field.set(instance, value);
}
}
return instance;
}
}
// 测试类
class Person {
private String name;
private int age;
private String city;
// 省略getter/setter...
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + ", city='" + city + "'}";
}
}
public class JsonExample {
public static void main(String[] args) throws Exception {
Person person = new Person();
// 使用反射设置字段值
Class<Person> clazz = Person.class;
Field nameField = clazz.getDeclaredField("name");
nameField.setAccessible(true);
nameField.set(person, "张三");
Field ageField = clazz.getDeclaredField("age");
ageField.setAccessible(true);
ageField.set(person, 25);
Field cityField = clazz.getDeclaredField("city");
cityField.setAccessible(true);
cityField.set(person, "北京");
// 序列化为JSON
String json = SimpleJsonSerializer.toJson(person);
System.out.println("序列化: " + json);
// 反序列化
Person newPerson = SimpleJsonSerializer.fromJson(json, Person.class);
System.out.println("反序列化: " + newPerson);
}
}
8.3 数据库ORM框架
import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
// 模拟简单的ORM框架
public class SimpleORM {
public static <T> List<T> query(Connection conn, Class<T> clazz, String sql) throws Exception {
List<T> result = new ArrayList<>();
try (PreparedStatement stmt = conn.prepareStatement(sql);
ResultSet rs = stmt.executeQuery()) {
ResultSetMetaData metaData = rs.getMetaData();
int columnCount = metaData.getColumnCount();
while (rs.next()) {
T obj = clazz.newInstance();
for (int i = 1; i <= columnCount; i++) {
String columnName = metaData.getColumnName(i);
Object columnValue = rs.getObject(i);
// 使用反射设置字段值
try {
Field field = clazz.getDeclaredField(columnName.toLowerCase());
field.setAccessible(true);
field.set(obj, columnValue);
} catch (NoSuchFieldException e) {
// 字段不存在,跳过
}
}
result.add(obj);
}
}
return result;
}
}
// 实体类
class User {
private int id;
private String name;
private String email;
@Override
public String toString() {
return "User{id=" + id + ", name='" + name + "', email='" + email + "'}";
}
}
public class ORMExample {
public static void main(String[] args) {
// 实际使用时需要真实的数据库连接
// 这里只是展示反射在ORM中的应用思路
System.out.println("ORM框架通常使用反射来实现对象关系映射");
}
}
九、反射的优缺点
优点:
- 灵活性:可以在运行时动态创建对象、调用方法
- 扩展性:可以实现插件化架构
- 框架开发:是很多框架(Spring、MyBatis等)的基础
缺点:
- 性能开销:反射操作比直接调用慢
- 安全性问题:可以绕过访问控制检查
- 代码复杂度:使代码难以理解和维护
- 调试困难:运行时错误难以追踪
十、性能优化建议
public class ReflectionPerformance {
private static final int LOOP_COUNT = 1000000;
// 普通方法调用
public static void normalCall() {
long start = System.currentTimeMillis();
Example example = new Example();
for (int i = 0; i < LOOP_COUNT; i++) {
example.doSomething();
}
long end = System.currentTimeMillis();
System.out.println("普通调用耗时: " + (end - start) + "ms");
}
// 反射方法调用
public static void reflectionCall() throws Exception {
long start = System.currentTimeMillis();
Example example = new Example();
Class<?> clazz = example.getClass();
Method method = clazz.getMethod("doSomething");
for (int i = 0; i < LOOP_COUNT; i++) {
method.invoke(example);
}
long end = System.currentTimeMillis();
System.out.println("反射调用耗时: " + (end - start) + "ms");
}
// 优化后的反射调用(缓存Method对象)
public static void optimizedReflectionCall() throws Exception {
long start = System.currentTimeMillis();
Example example = new Example();
Class<?> clazz = example.getClass();
Method method = clazz.getMethod("doSomething");
method.setAccessible(true); // 设置可访问,提高性能
for (int i = 0; i < LOOP_COUNT; i++) {
method.invoke(example);
}
long end = System.currentTimeMillis();
System.out.println("优化反射调用耗时: " + (end - start) + "ms");
}
static class Example {
public void doSomething() {
// 空方法,用于测试性能
}
}
public static void main(String[] args) throws Exception {
normalCall();
reflectionCall();
optimizedReflectionCall();
}
}
总结
反射是Java中非常强大的特性,它为框架开发、动态代理、测试工具等提供了基础支持。虽然反射有性能开销和安全风险,但在合适的场景下使用可以极大提高代码的灵活性和可扩展性。
使用建议:
- 在框架开发中大量使用
- 在业务代码中谨慎使用
- 注意性能优化,缓存反射对象
- 处理好安全检查异常

浙公网安备 33010602011771号