当前位置:首页 » 《关注互联网》 » 正文

【Java】深度解析Java的反射机制

4 人参与  2024年09月13日 08:01  分类 : 《关注互联网》  评论

点击全文阅读


反射(Reflection)

一、 反射的基本概念二、 获取类的信息三、 获取类的成员四、 动态创建对象五、 动态调用方法六、 动态访问和修改字段 总结
在这里插入图片描述
在这里插入图片描述

一、 反射的基本概念

反射是一种运行时机制,允许程序在运行时检查和操作类、方法、字段等。通过反射,你可以:

获取类的详细信息(类名、修饰符、父类、接口等)。获取类的方法、构造函数、字段等。动态调用方法或构造函数。动态访问和修改字段的值。

二、 获取类的信息

获取 Class 对象
有多种方法可以获取一个类的 Class 对象:

Class.forName(String className): 通过类的完全限定名获取 Class 对象。

ClassName.class: 通过类的字面常量获取 Class 对象。

object.getClass(): 通过对象实例获取 Class 对象。

// 获取 Class 对象的三种方式Class<?> clazz1 = Class.forName("java.util.ArrayList");Class<?> clazz2 = ArrayList.class;ArrayList<String> list = new ArrayList<>(); Class<?> clazz3 = list.getClass(); 

三、 获取类的成员

getDeclaredFields(): 获取类的所有字段(包括私有字段)。

getDeclaredMethods(): 获取类的所有方法(包括私有方法)。

getDeclaredConstructors(): 获取类的所有构造函数。

getField(String name): 获取类的指定字段(不包括私有字段)。

getMethod(String name, Class<?>… parameterTypes): 获取类的指定方法(不包括私有方法)。

getConstructor(Class<?>… parameterTypes): 获取类的指定构造函数。

Class<?> clazz = Class.forName("java.util.ArrayList"); // 获取所有声明的字段Field[] fields = clazz.getDeclaredFields();for (Field field : fields) {    System.out.println("字段: " + field.getName());} // 获取所有声明的方法Method[] methods = clazz.getDeclaredMethods();for (Method method : methods) {    System.out.println("方法: " + method.getName());} // 获取所有声明的构造函数Constructor<?>[] constructors = clazz.getDeclaredConstructors();for (Constructor<?> constructor : constructors) {    System.out.println("构造函数: " + constructor.getName());}

四、 动态创建对象

newInstance(): 使用无参构造函数创建对象。

Constructor.newInstance(Object… initargs): 使用指定构造函数创建对象。

Class<?> clazz = Class.forName("java.util.ArrayList"); // 使用无参构造函数创建对象Object obj1 = clazz.newInstance(); // 使用带参数的构造函数创建对象Constructor<?> constructor = clazz.getConstructor(Collection.class);Collection<String> collection = Arrays.asList("A", "B", "C");Object obj2 = constructor.newInstance(collection); System.out.println(obj1);System.out.println(obj2);

五、 动态调用方法

Method.invoke(Object obj, Object… args): 调用指定对象的该方法。

Class<?> clazz = Class.forName("java.util.ArrayList");Method method = clazz.getMethod("add", Object.class); ArrayList<String> list = new ArrayList<>();method.invoke(list, "Hello");System.out.println(list); // 输出: [Hello]

六、 动态访问和修改字段

Field.get(Object obj): 获取指定对象中此字段的值。

Field.set(Object obj, Object value): 设置指定对象中此字段的值。

 class MyClass {    private String field = "Initial Value";} Class<?> clazz = Class.forName("MyClass");Field field = clazz.getDeclaredField("field");field.setAccessible(true); // 如果字段是私有的,需要设置可访问 MyClass obj = new MyClass();System.out.println("原始字段值: " + field.get(obj)); // 获取字段值 field.set(obj, "New Value"); // 设置字段值System.out.println("修改后的字段值: " + field.get(obj)); // 获取字段值

结合注解与反射

注解与反射的结合非常常见,尤其在框架中,例如 Spring 和 Hibernate。通过反射机制,你可以在运行时读取注解信息,并根据这些信息执行特定的操作。

示例:简单的依赖注入
以下示例展示了如何通过注解和反射实现简单的依赖注入:

import java.lang.annotation.*;import java.lang.reflect.*; // 定义注解@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.FIELD)@interface Inject {} // 服务类class Service {    public void serve() {        System.out.println("Service is serving");    }} // 客户端类class Client {    @Inject    private Service service;     public void doSomething() {        service.serve();    }} // 注入依赖的工具类public class DependencyInjector {    public static void main(String[] args) throws Exception {        Client client = new Client();        injectDependencies(client);        client.doSomething();    }     public static void injectDependencies(Object obj) throws Exception {        Class<?> clazz = obj.getClass();        for (Field field : clazz.getDeclaredFields()) {// 遍历client的所有字段(变量).            if (field.isAnnotationPresent(Inject.class)) {// 获取带有Inject注解的变量, 把它注入到 Client 中                field.setAccessible(true);                Object dependency = field.getType().getConstructor().newInstance();                field.set(obj, dependency);// 通过field的set方法将service实例注入到client中            }        }    }}

在这个示例中:

@Inject 注解用于标注需要注入的字段。

DependencyInjector 类通过反射获取 Client 类中带有 @Inject 注解的字段,并动态实例化 Service 类的对象,注入到 Client 类的实例中。

Client 类调用 doSomething 方法时,Service 类的实例已经被注入并可以使用。

总结

反射是 Java 中非常强大和灵活的机制,通过它们可以实现许多高级功能,例如依赖注入、AOP、动态代理等。在实际开发中,理解和熟练运用这些技术,可以帮助你编写出更加灵活、可扩展的代码。

文章到这里就这束了!~


点击全文阅读


本文链接:http://zhangshiyu.com/post/159073.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

最新文章

  • 祖母寿宴,侯府冒牌嫡女被打脸了(沈屿安秦秀婉)阅读 -
  • 《雕花锦年,昭都旧梦》(裴辞鹤昭都)完结版小说全文免费阅读_最新热门小说《雕花锦年,昭都旧梦》(裴辞鹤昭都) -
  • 郊区41号(许洛竹王云云)完整版免费阅读_最新全本小说郊区41号(许洛竹王云云) -
  • 负我情深几许(白诗茵陆司宴)完结版小说阅读_最热门小说排行榜负我情深几许白诗茵陆司宴 -
  • 九胞胎孕妇赖上我萱萱蓉蓉免费阅读全文_免费小说在线看九胞胎孕妇赖上我萱萱蓉蓉 -
  • 为保白月光,侯爷拿我抵了债(谢景安花田)小说完结版_完结版小说全文免费阅读为保白月光,侯爷拿我抵了债谢景安花田 -
  • 陆望程映川上官硕《我的阿爹是带攻略系统的替身》最新章节阅读_(我的阿爹是带攻略系统的替身)全章节免费在线阅读陆望程映川上官硕
  • 郑雅琴魏旭明免费阅读_郑雅琴魏旭明小说全文阅读笔趣阁
  • 头条热门小说《乔书意贺宴临(乔书意贺宴临)》乔书意贺宴临(全集完整小说大结局)全文阅读笔趣阁
  • 完结好看小说跨年夜,老婆初恋送儿子故意出车祸_沈月柔林瀚枫完结的小说免费阅读推荐
  • 热推《郑雅琴魏旭明》郑雅琴魏旭明~小说全文阅读~完本【已完结】笔趣阁
  • 《你的遗憾与我无关》宋怀川冯洛洛无弹窗小说免费阅读_免费小说大全《你的遗憾与我无关》宋怀川冯洛洛 -

    关于我们 | 我要投稿 | 免责申明

    Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1