Java入门(8)--反射机制
Java反射机制:运行时的强大工具 🔍
🎯 掌握Java反射,让你的代码更具灵活性和扩展性!
在上一篇文章中,我们学习了Java网络编程的相关知识。今天,让我们深入探讨Java反射机制,了解如何在运行时操作类和对象! 💡
1. 反射机制基础 📚
反射是Java的一个强大特性,允许程序在运行时检查和操作类、接口、字段和方法。
1.1 获取Class对象
public class ReflectionBasics {public static void main(String[] args) {// 方法1:通过类名.classClass<?> class1 = String.class;// 方法2:通过对象.getClass()String str = "Hello";Class<?> class2 = str.getClass();// 方法3:通过Class.forName()try {Class<?> class3 = Class.forName("java.lang.String");} catch (ClassNotFoundException e) {e.printStackTrace();}// 打印类信息System.out.println("类名:" + class1.getName());System.out.println("简单类名:" + class1.getSimpleName());System.out.println("包名:" + class1.getPackageName());}
}
1.2 获取类的信息
public class ClassInfo {public static void main(String[] args) {Class<?> clazz = Person.class;// 获取所有public字段Field[] fields = clazz.getFields();// 获取所有字段(包括私有)Field[] declaredFields = clazz.getDeclaredFields();// 获取所有public方法Method[] methods = clazz.getMethods();// 获取所有方法(包括私有)Method[] declaredMethods = clazz.getDeclaredMethods();// 获取所有public构造器Constructor<?>[] constructors = clazz.getConstructors();// 获取所有构造器(包括私有)Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();}
}
2. 反射操作详解 🛠
2.0 反射性能优化
在开始介绍具体操作前,先了解一些性能优化技巧:
public class ReflectionPerformance {public static void main(String[] args) {// 1. 缓存Class对象Class<?> personClass = Person.class;// 2. 缓存Constructor/Method/Field对象Constructor<?> constructor;Method getNameMethod;Field nameField;try {constructor = personClass.getConstructor(String.class, int.class);getNameMethod = personClass.getMethod("getName");nameField = personClass.getDeclaredField("name");// 3. 一次性设置accessibleif (!nameField.canAccess(null)) {nameField.setAccessible(true);}// 4. 批量创建对象Person[] persons = new Person[100];for (int i = 0; i < 100; i++) {persons[i] = (Person) constructor.newInstance("person" + i, i);}// 5. 批量调用方法for (Person person : persons) {String name = (String) getNameMethod.invoke(person);// 处理结果...}} catch (Exception e) {e.printStackTrace();}}
}
2.1 创建对象
public class ObjectCreation {public static void main(String[] args) {try {// 获取Class对象Class<?> personClass = Class.forName("com.example.Person");// 方法1:使用默认构造器Object person1 = personClass.newInstance(); // 已过时// 方法2:获取特定构造器(推荐)Constructor<?> constructor = personClass.getConstructor(String.class, int.class);Object person2 = constructor.newInstance("张三", 25);} catch (Exception e) {e.printStackTrace();}}
}
2.2 访问和修改字段
public class FieldOperation {public static void main(String[] args) {try {Class<?> personClass = Person.class;Person person = new Person("张三", 25);// 获取指定字段Field nameField = personClass.getDeclaredField("name");// 设置私有字段可访问nameField.setAccessible(true);// 获取字段值String name = (String) nameField.get(person);System.out.println("原始名字:" + name);// 修改字段值nameField.set(person, "李四");System.out.println("修改后的名字:" + person.getName());} catch (Exception e) {e.printStackTrace();}}
}
2.3 调用方法
public class MethodInvocation {public static void main(String[] args) {try {Class<?> personClass = Person.class;Person person = new Person("张三", 25);// 获取public方法Method setNameMethod = personClass.getMethod("setName", String.class);// 调用方法setNameMethod.invoke(person, "李四");// 获取私有方法Method privateMethod = personClass.getDeclaredMethod("privateMethod");privateMethod.setAccessible(true);privateMethod.invoke(person);} catch (Exception e) {e.printStackTrace();}}
}
3. 反射应用场景与实战 🎯
3.0 注解处理
// 自定义注解
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiMapping {String value(); // API路径String method() default "GET"; // HTTP方法String desc() default ""; // API描述
}@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiParam {String value(); // 参数名boolean required() default true; // 是否必需String desc() default ""; // 参数描述
}// 注解处理器
public class ApiScanner {public static void scanApi(String packageName) {// 获取包下所有类Reflections reflections = new Reflections(packageName);Set<Class<?>> apiClasses = reflections.getTypesAnnotatedWith(ApiMapping.class);for (Class<?> apiClass : apiClasses) {ApiMapping classMapping = apiClass.getAnnotation(ApiMapping.class);String basePath = classMapping.value();// 扫描类中的API方法for (Method method : apiClass.getDeclaredMethods()) {if (method.isAnnotationPresent(ApiMapping.class)) {ApiMapping methodMapping = method.getAnnotation(ApiMapping.class);String apiPath = basePath + methodMapping.value();System.out.println("发现API: " + apiPath);System.out.println("HTTP方法: " + methodMapping.method());System.out.println("描述: " + methodMapping.desc());// 处理方法参数Parameter[] parameters = method.getParameters();for (Parameter param : parameters) {if (param.isAnnotationPresent(ApiParam.class)) {ApiParam apiParam = param.getAnnotation(ApiParam.class);System.out.println("参数: " + apiParam.value());System.out.println("必需: " + apiParam.required());System.out.println("描述: " + apiParam.desc());}}}}}}
}// 使用示例
@ApiMapping("/user")
public class UserController {@ApiMapping(value = "/add", method = "POST", desc = "添加用户")public void addUser(@ApiParam(value = "name", desc = "用户名") String name,@ApiParam(value = "age", desc = "年龄") int age) {// 实现逻辑}@ApiMapping(value = "/{id}", desc = "获取用户信息")public User getUser(@ApiParam(value = "id", desc = "用户ID") String id) {// 实现逻辑return null;}
}### 3.1 动态代理```java
public interface UserService {void addUser(String name);void deleteUser(String name);
}public class UserServiceImpl implements UserService {@Overridepublic void addUser(String name) {System.out.println("添加用户:" + name);}@Overridepublic void deleteUser(String name) {System.out.println("删除用户:" + name);}
}public class LogHandler implements InvocationHandler {private final Object target;public LogHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("开始执行:" + method.getName());Object result = method.invoke(target, args);System.out.println("执行结束:" + method.getName());return result;}
}// 使用示例
public class ProxyDemo {public static void main(String[] args) {UserService userService = new UserServiceImpl();UserService proxy = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(),userService.getClass().getInterfaces(),new LogHandler(userService));proxy.addUser("张三");proxy.deleteUser("李四");}
}
3.2 简易依赖注入框架
// 作用域注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Scope {String value() default "singleton"; // singleton/prototype
}// 服务注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Service {String value() default "";
}// 增强版依赖注入容器
public class EnhancedDIContainer {private final Map<Class<?>, Object> singletons = new HashMap<>();private final Map<Class<?>, Class<?>> implementations = new HashMap<>();private final Set<Class<?>> prototypeClasses = new HashSet<>();// 注册接口实现public void registerImplementation(Class<?> interfaceClass, Class<?> implClass) {implementations.put(interfaceClass, implClass);// 检查作用域if (implClass.isAnnotationPresent(Scope.class)) {Scope scope = implClass.getAnnotation(Scope.class);if ("prototype".equals(scope.value())) {prototypeClasses.add(implClass);}}}// 获取实例public Object getInstance(Class<?> clazz) {// 检查是否是接口if (clazz.isInterface()) {Class<?> implClass = implementations.get(clazz);if (implClass == null) {throw new RuntimeException("未找到接口实现: " + clazz.getName());}clazz = implClass;}// 检查作用域if (prototypeClasses.contains(clazz)) {return createInstance(clazz);}// 单例模式return singletons.computeIfAbsent(clazz, this::createInstance);}// 创建实例private Object createInstance(Class<?> clazz) {try {Object instance = clazz.getDeclaredConstructor().newInstance();injectDependencies(instance);return instance;} catch (Exception e) {throw new RuntimeException("创建实例失败: " + clazz.getName(), e);}}// 注入依赖private void injectDependencies(Object instance) {Class<?> clazz = instance.getClass();for (Field field : clazz.getDeclaredFields()) {if (field.isAnnotationPresent(Autowired.class)) {field.setAccessible(true);try {Object dependency = getInstance(field.getType());field.set(instance, dependency);} catch (IllegalAccessException e) {throw new RuntimeException("依赖注入失败", e);}}}}// 扫描并注册服务public void scanPackage(String basePackage) {Reflections reflections = new Reflections(basePackage);Set<Class<?>> serviceClasses = reflections.getTypesAnnotatedWith(Service.class);for (Class<?> serviceClass : serviceClasses) {// 获取服务实现的接口Class<?>[] interfaces = serviceClass.getInterfaces();if (interfaces.length > 0) {registerImplementation(interfaces[0], serviceClass);}}}
}// 使用示例
@Service
@Scope("singleton")
public class UserServiceImpl implements UserService {@Autowiredprivate UserRepository userRepository;@Overridepublic void addUser(String name) {// 实现逻辑}
}// 测试代码
public class DITest {public static void main(String[] args) {EnhancedDIContainer container = new EnhancedDIContainer();// 扫描服务container.scanPackage("com.example");// 获取服务实例UserService userService = (UserService) container.getInstance(UserService.class);userService.addUser("张三");}
}```java
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
}public class DIContainer {private final Map<Class<?>, Object> instances = new HashMap<>();public void register(Class<?> clazz) {try {Object instance = clazz.newInstance();instances.put(clazz, instance);} catch (Exception e) {throw new RuntimeException("注册失败", e);}}public void inject(Object object) {Class<?> clazz = object.getClass();for (Field field : clazz.getDeclaredFields()) {if (field.isAnnotationPresent(Autowired.class)) {Class<?> type = field.getType();Object dependency = instances.get(type);if (dependency != null) {field.setAccessible(true);try {field.set(object, dependency);} catch (IllegalAccessException e) {throw new RuntimeException("注入失败", e);}}}}}
}
3.3 单元测试框架
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {
}public class TestRunner {public static void runTests(Class<?> testClass) {Object instance;try {instance = testClass.newInstance();} catch (Exception e) {throw new RuntimeException("创建测试实例失败", e);}for (Method method : testClass.getDeclaredMethods()) {if (method.isAnnotationPresent(Test.class)) {try {method.invoke(instance);System.out.println(method.getName() + " - 通过");} catch (Exception e) {System.out.println(method.getName() + " - 失败: " + e.getCause().getMessage());}}}}
}
4. 反射高级特性与使用建议 💡
4.1 反射获取泛型信息
public class GenericTypeDemo {// 泛型字段private List<String> stringList;private Map<String, Integer> stringIntMap;public static void main(String[] args) throws Exception {Class<?> clazz = GenericTypeDemo.class;// 获取字段的泛型信息Field stringListField = clazz.getDeclaredField("stringList");ParameterizedType listType = (ParameterizedType) stringListField.getGenericType();Class<?> listElementType = (Class<?>) listType.getActualTypeArguments()[0];System.out.println("List元素类型: " + listElementType);// 获取Map的泛型信息Field mapField = clazz.getDeclaredField("stringIntMap");ParameterizedType mapType = (ParameterizedType) mapField.getGenericType();Class<?> keyType = (Class<?>) mapType.getActualTypeArguments()[0];Class<?> valueType = (Class<?>) mapType.getActualTypeArguments()[1];System.out.println("Map键类型: " + keyType);System.out.println("Map值类型: " + valueType);}
}// 泛型方法处理
public class GenericMethodDemo {public <T> List<T> createList(Class<T> elementType, int size) {List<T> list = new ArrayList<>();try {for (int i = 0; i < size; i++) {list.add(elementType.getDeclaredConstructor().newInstance());}} catch (Exception e) {e.printStackTrace();}return list;}// 获取方法返回值的泛型信息public static void analyzeMethod() throws Exception {Method method = GenericMethodDemo.class.getMethod("createList", Class.class, int.class);Type returnType = method.getGenericReturnType();if (returnType instanceof ParameterizedType) {ParameterizedType paramType = (ParameterizedType) returnType;Type[] typeArgs = paramType.getActualTypeArguments();System.out.println("返回类型的泛型参数: " + Arrays.toString(typeArgs));}}
}
4.2 类型擦除与运行时类型
public class TypeErasureDemo {public static void main(String[] args) {List<String> stringList = new ArrayList<>();List<Integer> intList = new ArrayList<>();// 由于类型擦除,这两个list的Class对象是相同的System.out.println(stringList.getClass() == intList.getClass()); // true// 但我们可以通过反射获取泛型信息class StringListWrapper extends ArrayList<String> {}Type type = StringListWrapper.class.getGenericSuperclass();if (type instanceof ParameterizedType) {ParameterizedType pType = (ParameterizedType) type;Type[] types = pType.getActualTypeArguments();System.out.println("实际类型参数: " + types[0]); // class java.lang.String}}
}
4.3 反射与注解处理器
-
性能考虑:
- 反射操作比直接调用慢
- 缓存反射结果
- 适度使用反射
-
安全建议:
- 谨慎使用setAccessible
- 注意权限检查
- 防止恶意代码注入
-
最佳实践:
- 优先使用常规方式
- 合理使用反射
- 注意异常处理
- 保持代码可读性
练习项目 🎯
- 实现简单的依赖注入容器
- 创建注解处理器
- 开发配置文件解析器
- 实现简单的ORM框架
结语 📝
Java反射机制为我们提供了强大的运行时编程能力。合理使用反射,可以让我们的代码更加灵活和可扩展!
如果你觉得这篇文章有帮助,欢迎点赞转发,也期待在评论区看到你的想法和建议!👇
咱们下期见!