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 反射与注解处理器

  1. 性能考虑:

    • 反射操作比直接调用慢
    • 缓存反射结果
    • 适度使用反射
  2. 安全建议:

    • 谨慎使用setAccessible
    • 注意权限检查
    • 防止恶意代码注入
  3. 最佳实践:

    • 优先使用常规方式
    • 合理使用反射
    • 注意异常处理
    • 保持代码可读性

练习项目 🎯

  1. 实现简单的依赖注入容器
  2. 创建注解处理器
  3. 开发配置文件解析器
  4. 实现简单的ORM框架

结语 📝

Java反射机制为我们提供了强大的运行时编程能力。合理使用反射,可以让我们的代码更加灵活和可扩展!

如果你觉得这篇文章有帮助,欢迎点赞转发,也期待在评论区看到你的想法和建议!👇

咱们下期见!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/59426.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Aurora 64b/66bIP核学习

本文作为在学习使用aurora IP核的道路上&#xff0c;找到的一些对该IP讲解比较详细的资料&#xff0c;记录下来&#xff0c;便于日后翻阅&#xff0c;温故知新。 Aurora IP的特点 Aurora 协议在 2002 年由 Xilinx 公司首次提出&#xff0c;是由Xilinx提供的一个开源、免费的链…

树叶分类竞赛(Baseline)以及kaggle的GPU使用

树叶分类竞赛(Baseline)-kaggle的GPU使用 文章目录 树叶分类竞赛(Baseline)-kaggle的GPU使用竞赛的步骤代码实现创建自定义dataset定义data_loader模型定义超参数训练模型预测和保存结果 kaggle使用 竞赛的步骤 本文来自于Neko Kiku提供的Baseline&#xff0c;感谢大佬提供代码…

服务器作业(2)

架设一台NFS服务器&#xff0c;并按照以下要求配置 关闭防火墙 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 配置文件设置&#xff1a; [rootlocalhost ~]# vim /etc/exports 1、开放/nfs/shared目录&#xff0c;供所有用户查询资料 共享…

014:无人机遥控器操作

摘要&#xff1a;本文详细介绍了无人机遥控器及其相关操作。首先&#xff0c;解释了油门、升降舵、方向舵和副翼的概念、功能及操作方式&#xff0c;这些是控制无人机飞行姿态的关键部件。其次&#xff0c;介绍了美国手、日本手和中国手三种不同的操作模式&#xff0c;阐述了遥…

Redis的持久化以及性能管理

目录 一、Redis持久化概述 1.什么是Redis持久化 2.持久化方式 3.RDB持久化 3.1概念 3.2触发条件 3.3执行流程 3.4启动时加载 4. AOF持久化 4.1概念 4.2启动AOF 4.3执行流程 4.4启动时加载 5.RDB和AOF的优缺点 二、Redis性能管理 1.查看Redis内存使用 2…

什么是JS的垃圾回收机制?

在JavaScript中&#xff0c;垃圾回收&#xff08;Garbage Collection&#xff0c;简称GC&#xff09;是一种自动内存管理机制。它的主要任务是识别并回收不再被使用的对象&#xff0c;以释放内存空间。以下是关于JavaScript垃圾回收机制的详细解释&#xff1a; 标记清除算法 …

Java项目实战II基于Java+Spring Boot+MySQL的高校办公室行政事务管理系统(源码+数据库+文档)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 在高等教育…

HTB:PermX[WriteUP]

目录 连接至HTB服务器并启动靶机 1.How many TCP ports are listening on PermX? 使用nmap对靶机TCP端口进行开放扫描 2.What is the default domain name used by the web server on the box? 使用curl访问靶机80端口 3.On what subdomain of permx.htb is there an o…

nginx安装ssl模块教程

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、openssl是什么&#xff1f;二、ssl证书免费申请地址三、安装步骤1.nginx安装ssl模块 总结 一、openssl是什么&#xff1f; OpenSSL 不仅是一个独立的工具包,它…

在Vue和OpenLayers中使用移动传感器实现飞机航线飞行模拟

项目实现的核心代码 项目概述 该项目的目标是使用Vue.js作为前端框架&#xff0c;结合OpenLayers用于地图显示&#xff0c;实时获取来自手机传感器的数据&#xff08;如经纬度、高度、速度&#xff09;来模拟飞机在地图上的飞行轨迹。整体架构如下&#xff1a; Vue.js 用于构建…

分析 SQL 语句的一般步骤

analyse-sql 数据库的性能调优是一个很大的话题。但是对于开发人员来讲&#xff0c;掌握一些常用的 SQL 优化手段却不是什么难事。 从本章节开始&#xff0c;将连载总结常用的适合于开发人员的 SQL 优化手段与大家分享。 要想解决性能优化的问题&#xff0c;首先要想办法发现哪…

数据库基础(2) . 安装MySQL

0.增加右键菜单选项 添加 管理员cmd 到鼠标右键 运行 reg文件 在注册表中添加信息 这样在右键菜单中就有以管理员身份打开命令行的选项了 1.获取安装程序 网址: https://dev.mysql.com/downloads/mysql/ 到官网下载MySQL8 的zip包, 然后解压 下载后的包为: mysql-8.0.16-…

文心一言 VS 讯飞星火 VS chatgpt (383)-- 算法导论24.5 3题

三、对引理 24.10 的证明进行改善&#xff0c;使其可以处理最短路径权重为 ∞ ∞ ∞ 和 − ∞ -∞ −∞ 的情况。引理 24.10(三角不等式)的内容是&#xff1a;设 G ( V , E ) G(V,E) G(V,E) 为一个带权重的有向图&#xff0c;其权重函数由 w : E → R w:E→R w:E→R 给出&…

深度学习基础知识-损失函数

目录 1. 均方误差&#xff08;Mean Squared Error, MSE&#xff09; 2. 平均绝对误差&#xff08;Mean Absolute Error, MAE&#xff09; 3. Huber 损失 4. 交叉熵损失&#xff08;Cross-Entropy Loss&#xff09; 5. KL 散度&#xff08;Kullback-Leibler Divergence&…

2024 CSS保姆级教程二 - BFC详解

前言 - CSS中的文档流 在介绍BFC之前&#xff0c;需要先给大家介绍一下文档流。​ 我们常说的文档流其实分为定位流、浮动流、普通流三种。​ ​ 1. 绝对定位(Absolute positioning)​ 如果元素的属性 position 为 absolute 或 fixed&#xff0c;它就是一个绝对定位元素。​ 在…

Qt5 读写共享内存,已验证,支持汉字的正确写入和读取

Qt5&#xff0c;读写共享内存&#xff0c;Windows下同一个进程下可测试&#xff1b; 通过查看控制台输出即可看到写入和读出的内容&#xff1b; 相比网上其他介绍的方法&#xff0c;大部分均不支持汉字的正常读取&#xff0c;下面方法已经做了汉字存储的支持&#xff0c;可以…

Java图片转word

该方法可以控制一页是否只显示存放一张图片 第一步 <dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>5.2.3</version></dependency><dependency><groupId>org.apache…

VueSSR详解 VueServerRenderer Nutx

SSR Vue中的SSR&#xff08;Server-Side Rendering&#xff0c;服务器端渲染&#xff09;是一种将页面的渲染工作从客户端转移到服务器端的技术。以下是对Vue中SSR的详细解释&#xff1a; 一、SSR的工作原理 在传统的客户端渲染&#xff08;CSR&#xff09;中&#xff0c;页面的…

指针(c语言)

一.指针的定义 1.内存被划分为一个一个内存单元&#xff0c;对内存单元进行编号&#xff0c;这些编号称为内存单元的地址&#xff0c; 其中指针就是存放地址的容器 2.平常说的指针&#xff0c;其实就是指针变量 注意&#xff1a; 1个内存单元的大小是1个字节&#xff0c;如果是…

一篇文章了解TCP/IP模型

TCP/IP模型&#xff0c;即传输控制协议/互联网协议模型&#xff08;Transmission Control Protocol/Internet Protocol Model&#xff09;&#xff0c;是互联网及许多其他网络上使用的分层通信模型。以下是对TCP/IP模型的详细介绍&#xff1a; 一、定义与组成TCP/IP模型是一个四…