前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java反射机制详解与“动”在哪里

Java反射机制详解与“动”在哪里

原创
作者头像
小明爱吃火锅
发布2023-10-30 20:18:49
2950
发布2023-10-30 20:18:49
举报
文章被收录于专栏:小明说Java小明说Java

?

一、什么是反射机制?

反射机制是指在运行时动态地获取类的信息,并能够通过这些信息对类的对象进行操作。Java中的反射机制包括获取类信息获取成员信息创建对象调用方法等操作。通过反射机制,我们可以在运行时动态地了解类的结构、属性和方法等信息,从而实现对类的动态操作。通俗来讲,实例化号对象之后,反过来获取Class对象(一个类只有一个Class对象),这个对象包含了完整的类的结构信息,这个对象就像一个镜子,通过这个镜子看到类的结构,所以就就要反射。

二、反射的动态体现在哪里?

上面介绍反射机制的时候,多次提到动态,这也是反射的一个重要存在的意义。反射的动态性体现在可以在运行时根据需要动态地获取和操作类的信息,使得程序更加灵活、可扩展和可维护。比如:

  1. 可以在运行时动态地创建对象:通过反射,我们可以在运行时根据需要动态地创建类的实例,而不需要在编译时就确定要创建的对象类型。
  2. 可以动态地调用方法:通过反射,我们可以根据需要动态地调用类的方法。我们可以在运行时获取到方法的Method对象,并使用Method对象的invoke()方法来调用该方法。这种方式可以让我们在运行时根据不同的条件来选择调用不同的方法。
  3. 可以动态地访问字段和属性:通过反射,我们可以动态地获取类的字段和属性信息。我们可以通过Field对象来获取和修改类的字段值,或者通过获取类的属性列表来获取类的属性信息。这种方式可以让我们在运行时根据需要来访问和修改类的字段和属性。
  4. 可以动态地处理注解:注解是Java中一种重要的元数据机制。通过反射,我们可以动态地获取类的注解信息,并根据注解来进行一些特定的处理。这种方式可以让我们在运行时根据需要来处理类的注解信息。

对于第一次听到这个反射可以动态获取对象,是有点抽象的,包括我本人,可以这样通俗理解: 传统如果实例化一个类的对象,常规是使用new操作符,但这样就意味着创建的对象是固定的,要修改成别的就需要更改源代码。比如:

代码语言:javascript
复制
Person person = new Person();

而反射则可以通过Class实例在运行时实例化对象。如果要修改实例化的对象只需要修改配置文件就行了,极大地增加了程序灵活性,避免修改代码然后重新编译。比如上面获取对象:

代码语言:javascript
复制
???????Class aClasss = Class.forName("com.meeting.bishi2.Peason");

这样就可以将“com.meeting.bishi2.Peason”放到配置文件,如果要改创建其他类,就可以直接修改配置文件,程序都不用重新启动。

这就是反射动态的体现。

三、反射基本使用(三部曲)

Java中实现反射机制的常用API包括:

  1. Class类:代表一个类,可以通过Class对象获取类的名称、成员变量、方法等信息。
  2. Method类:代表一个方法,可以通过Method对象获取方法的名称、参数列表、返回值等信息。
  3. Field类:代表一个成员变量,可以通过Field对象获取成员变量的名称、类型等信息。
  4. Constructor类:代表一个构造函数,可以通过Constructor对象获取构造函数的参数列表等信息。

反射基本使用主要通过以下三部曲进行操作:

1.获取Class对象

a.已知具体类,通过类的class属性获取,这个方法最安全可靠,程序性能最高

代码语言:javascript
复制
Class pclass = Peason.class;

b.已知某个类的实例,已经实例化了,调用该实例的getClass方法获取class对象

代码语言:javascript
复制
 Class class = peason.getClass();

c.通过全类名,用Class类的静态方法forNema()获取,之后还能通过newInstance调用无参构造器去实例化一个对象

代码语言:javascript
复制
Class aClasss = Class.forName("com.meeting.bishi2.Peason");

以上三种反射获取的都是通过Class对象,他们的hashcode都是一样的。

2.调用method方法

获取Class类对象之后就可以调用对应的方法,比如获取类方法,属性等等。

实例说明,比如Person类中有getAll()方法,

代码语言:javascript
复制
    public void addAll(){

    }

可以通过反射获取该方法:

代码语言:javascript
复制
        Class c3 = Class.forName("com.meeting.bishi2.Peason");
        Method add = c3.getMethod("addAll");
        System.out.println(add);

可以正确获取到这个getAll方法

3.invoke执行方法

上面获取到方法之后,接下来就可以通过反射调用该方法进行执行了。格式如下:

代码语言:javascript
复制
Method method= 类.getMethod(方法名);
method.invoke(实例对象名, 参数....);

或者

Method.invoke(实例对象名, 方法, 参数....);

安装格式,运用反射调用addAll方法如下:

代码语言:javascript
复制
        Class c3 = Class.forName("com.meeting.bishi2.Peason");
        Method add = c3.getMethod("addAll");
        add.invoke(c3);

但是运行结果报错,通过报错提示也可以看到,对象需要被实例

所以invoke的对象必须先实现,可以调用 c3.newInstance() 实例:

代码语言:javascript
复制
        Method add = c3.getMethod("addAll");
        add.invoke(c3.newInstance());

最终可以真确调用addAll方法,运行结果如下,

四、反射的实际应用

1)spring底层创建对象,其实spring框架初始化bean,也是运用反射的,大致如下

代码语言:javascript
复制
        Class c4 = Class.forName("com.meeting.bishi2.Peason");
//        1)通过newInstance调用无参构造器去实例化一个对象。类必须包含有无参构造器
        Peason person3 = (Peason) c4.newInstance();
        System.out.println(person3);
//        2)通过构造器创建对象,指定构造器创建对象
        Constructor constructor = c4.getConstructor(String.class, String.class);
        Peason person4 = (Peason) constructor.newInstance("aaa","123");
        System.out.println(person4);

2)不同类型的集合进行复制,比如将List数据拷贝到A仍然有List

代码语言:javascript
复制
// 利用反射,不用关心类型,内部直接调用方法
List<String> numbers = new ArrayList<String>();
numbers.add("1");
numbers.add("2");
numbers.add("3");
ArrayList<Integer> integers = new ArrayList<Integer>();
Method addMethod = integers.getClass().getMethod("add", Object.class);
for (String number : numbers) {
    // 给integers这个对象invoke,addMethod方法执行,入参是number
    addMethod.invoke(integers,number);
}
System.out.println(integers);

总结

反射可以能在运行时获取类指定信息,可以增加程序灵活性。在框架中就大量通过反射来增加程序灵活性,避免程序写死在源代码中。但是在使用中也是要注意的,或者说反射也有缺点:

  • 反射导致性能下降(创建很多对象才会)原因:读取class,解析classname,匹配,安全性校验耗时
  • 反射包括了一些动态类型,JVM 无法对这些代码进行优化,因此反射操作的效率要比那些非反射操作低得多。
  • 如果一个功能能不用反射实现就不用反射,但有些地方为了保证灵活性也不得不用,所以酌情考虑。

?

我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、什么是反射机制?
  • 二、反射的动态体现在哪里?
  • 三、反射基本使用(三部曲)
    • 1.获取Class对象
      • 2.调用method方法
        • 3.invoke执行方法
        • 四、反射的实际应用
        • 总结
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
        http://www.vxiaotou.com