Java基础-基本原理-1、反射
1. 定义
在《Thinking in Java》一书中曾说到:
反射机制并没有什么神奇之处,当通过反射与一个未知类型的对象打交道时,JVM 只是简单地检查这个对象,看它属于哪个特定的类,再用它做其他事情之前必须先加载那个类的 Class 对象,那个类的 .class 文件对于 JVM 来说必须是可获取的:要么在本地,要么在网络。普通方式和反射调用区别在于,编译器在编译时打开和检查 .class 文件,而对于反射机制来说,.class 文件在编译时是不可获取的,所以是在运行时打开和检查 .class 文件。
多态也在普通方式的范畴内。RTTI,即 Run-Time Type Identification 运行时类型认定,通过运行时类型信息程序能够使用父类的指针或引用来检查这些指针或引用所指的对象的实际派生类型,是多态实现的技术基础。RTTI 的功能主要是通过 Class 类文件实现的,更精确一点是通过 Class 类文件的方法表实现的。虽然是运行时判断所调用方法具体属于哪个类型,但是父类、子类的所有信息,在编译期是已经知道的了,即.class 文件在编译时已经获取到了。而对于反射机制来说,.class 文件在编译时是不可获取的,在运行时才获取到。
https://juejin.im/post/5a44c0ad518825455f2f96e5
java 的反射机制是指在程序运行状态中,给定任意一个类,都可以获取到这个类的属性和方法;给定任意一个对象都可以调用这个对象的属性和方法,这种动态的获取类的信息和调用对象的方法的功能称之为 java 的反射机制。
一言以蔽之:反射机制可以让你在程序运行时,拿到任意一个类的属性和方法并调用它。
2. 功能
- 运行时构造一个类的对象;
- 运行时获取一个类所具有的的成员变量和方法;
- 运行时调用任意一个对象的方法;
- 生成动态代理;
3. 使用方法
4. 优缺点
4.1. 优点
- 增加程序的灵活性,可以在运行的过程中动态对类进行修改和操作
- 提高代码的复用率,比如动态代理,就是用到了反射来实现
- 可以在运行时轻松获取任意一个类的方法、属性,并且还能通过反射进行动态调用
4.2. 缺点
- 反射会涉及到动态类型的解析,所以 JVM 无法对这些代码进行优化,导致性能要比非反射调用更低。
- 使用反射以后,代码的可读性会下降
- 反射可以绕过一些限制访问的属性或者方法,可能会导致破坏了代码本身的抽象性
5. 方法调用
5.1. 反射
5.2. MethodHandles
从目前接触到的 API 来看,似乎和以前用的反射区别并不大,其实不然,上面的特性包含在 JSR 292 中,提供了比反射 API 更加强大的动态方法调用能力,并且新增了一个 java 虚拟机指令 invokedynamic
,invokedynamic
指令通过引导方法(bootstrap method,BSM)机制来使用方法句柄。有关该指令更详细的信息可以参考 Java 虚拟机规范。
另外,在 JDK9 中新增了 Variable Handles
(变量句柄)相关功能,主要是用来取代 java.util.concurrent.atomic
包以及 sun.misc.Unsafe
类的功能,在 Lookup 类中,新增了 findVarHandle
方法来获取变量句柄,提供了各种细粒度的原子或有序性操作,更加安全和性能更高,毕竟 sun.misc.Unsafe
以后不推荐使用了,不安全。
参考:
这样看下来,MethodHandle 方法句柄的调用方式明显比 reflect 反射调用的方式至少在代码层面要繁琐很多。
并且对于 MethodHandle 而言,没有 Method.setAccessible
之类的操作,导致 private 和 protected 方法只有在类的内部代码中才能使用。甚至使用方法上甚至还要自己指定对于的 JVM 调用方式(invokevirutal / invokespecial / invokestatic)。
那 MethodHandle 方法在 Java7 中引入的意义何在呢?
❕ ^loszgb
最大的一个原因是出于性能考虑的,MethodHandle 的访问检查是在创建时进行校验的,而不是在实际调用时。这也就意味着生成了一个 MethodHandle 方法句柄之后,多次调用仅有一次权限检查,而 reflect 反射会在每次 invoke 时进行校验。
并且对于 JVM 而言,可以完全透视 MethodHandle 并将尝试对其进行优化,从而获得更好的性能。
5.2.1. 性能对比
https://www.cnblogs.com/danzZ/p/14190415.html
https://blog.51cto.com/u_15127639/2873107
https://ljd1996.github.io/2019/10/21/Java%E5%8F%8D%E5%B0%84/
6. 实战经验
7. 参考与感谢
https://zhuanlan.zhihu.com/p/519992996
https://blog.csdn.net/wenyuan65/article/details/81145900
https://blog.51cto.com/u_15127639/2873107
https://www.cnblogs.com/danzZ/p/14190415.html