【Java反射详解】

简介: 【Java反射详解】

Java反射详解

🎊专栏【Java】 🍔喜欢的诗句:关山难越,谁悲失路之人。

萍水相逢,尽是他乡之客。

🎆音乐分享【Counting Stars 】

欢迎并且感谢大家指出问题🥰

1.什么是反射

所谓的反射就是java语言在运行时拥有的一种自观的能力,反射使您的程序代码能够得到装载到JVM中的

类的内部信息,允许您执行程序时才得到需要类的内部信息,而不是在编写代码的时候就必须要知道所需

类的内部信息;也可以通俗的将这种动态获取信息以及动态调用对象的方法称为Java的反射机制.

通过Java的反射机制,程序猿们可以更深入的控制程序的运行过程,如在程序运行时对用户输入的信息进行
验证,还可以逆向控制程序的执行过程,这也使反射成为构建灵活的应用的主要工具。

2. 反射原理大解析

2.1 反射的常用类和函数

  • Java反射机制的实现要借助于4个类:
  • Class 类对象
  • Constructor 类的构造器对象
  • Field 类的属性对象
  • Method 类的方法对象

2.2 Class 类包含的方法

通过这四个对象我们可以粗略的看到一个类的各个组成部分。其中最核心的就是Class类,它是实现反射

的基础,Class类包含的方法主要有

2.3 反射的主要方法

应用反射时我们最关心的一般是一个类的构造器、属性和方法,下面我们主要介绍Class类中针对这三个

元素的方法:

2.3.1 得到构造器的方法

2.3.2 获得字段信息的方法

2.3.3 获得方法信息的方法

2.4 反射实战的基本步骤

上面就是最常见的反射使用的例子,前两行实现了类的装载、链接和初始化(newInstance方法实际上也是使用反射调用了 方法),后两行实现了从class对象中获取到method对象然后执行反射调用。下面简单分析一下该代码的具体原理。上就是最常见的反射使用的例子,前两行实现了类的装载、链接和初始化(newInstance方法实际上也是使用反射调用了 法),后两行实现了从class对象中获取到method对象然后执行反射调用。下面简单分析一下该代码的具体原理。

2.4.1 获得类的Class对象

通常有三种不同的方法:

1)Class c = Class.forName(“java.lang.String”)

2)Class c = MyClass.class

3)对于基本数据类型可以用Class c = int.class 或 Class c = Integer.TYPE这样的语句.

举个小栗子:先通过反射机制得到某个类的构造器,然后调用该构造器创建该类的一个实例

PS:反射的原理之一其实就是动态的生成类似于上述的字节码,加载到jvm中运行。

设想一下,上面的代码中,如果想要实现 method.invoke(action,null) 调用action对象的 myMethod

方法,只需要实现这样一个Method类即可

2.4.2 获取 Method 对象

首先来看一下Method对象是如何生成的:

使用Method m =myclass.getMethod(“myMethod”)获得了一个Class对象

接着对其进行判断,如果没有对应的cache,那么JVM就会为其创建一个并放入缓冲空间

处理器再判断Cache中是否存在"myMethod"

如果没有则返回NoSuchMethodException

如果存在那么就Copy一份"myMethod"对象并返回

上面的Class对象是在加载类时由JVM构造的,JVM为每个类管理一个独一无二的Class对象,这份Class对

象里维护着该类的所有Method,Field,Constructor的cache,这份cache也可以被称作根对象。每次

getMethod获取到的Method对象都持有对根对象的引用,因为一些重量级的Method的成员变量(主要

是MethodAccessor),我们不希望每次创建Method对象都要重新初始化,于是所有代表同一个方法的

Method对象都共享着根对象的MethodAccessor,每一次创建都会调用根对象的copy方法复制一份:

2.4.3 调用invoke()方法

获取到Method对象之后,调用invoke方法的流程如下:

m.invoke(obj,param);

首先调用MethodAccess.invoke

如果该方法的累计调用次数<=15,会创建出NativeMethodAccessorImp

如果该方法的累计调用次数>15,会由java代码创建出字节码组装而成的

MethodAccessorImpl

我们可以看到,调用Method.invoke之后,会直接去调 MethodAccessor.invoke 。MethodAccessor就

是上面提到的所有同名method共享的一个实例,由ReflectionFactory创建。创建机制采用了一种名为

inflation的方式(JDK1.4之后):如果该方法的累计调用次数<=15,会创建出

NativeMethodAccessorImpl,它的实现就是直接调用native方法实现反射;如果该方法的累计调用次数>15,会由java代码建出字节码组装而成的MethodAccessorImpl。(是否采用inflation和15这个数字都可以在jvm参数中调整)以调用MyClass.myMethod(String s) 为例,生成出的MethodAccessorImpl字节码翻译成Java代码大

致如下

通过对java运行过程的详细分析,我们可以发现其中第1次和第16次调用是最耗时的(初始化

NativeMethodAccessorImpl和字节码拼装MethodAccessorImpl)。初始化不可避免,因而native方式的

初始化会更快,所以前几次的调用会采用native方法。

随着调用次数的增加,每次反射都使用JNI跨越native边界会对优化有阻碍作用,相对来说使用拼装出的

字节码可以直接以Java调用的形式实现反射,发挥了JIT优化的作用,避免了JNI为了维护OopMap

(HotSpot用来实现准确式GC的数据结构)进行封装/解封装的性能损耗。

在已经创建了MethodAccessor的情况下,使用Java版本的实现会比native版本更快。所以当调用次数到

达一定次数(15次)后,会切换成Java实现的版本,来优化未来可能的更频繁的反射调用。

3 Java反射的应用(Hibernate框架)

前面我们已经知道,Java 反射机制提供了一种动态链接程序组件的多功能方法,它允许程序创建和控制

任何类的对象(根据安全性限制)之前,无需提前硬编码目标类。这些特性使得反射特别适用于创建以非常

普通的方式与对象协作的库。例如,反射经常在持续存储对象为数据库、XML或其它外部格式的框架中

使用。下面就已Hibernate框架为例像大家阐述一下反射的重要意义。

Hibernate是一个屏蔽了JDBC,实现了ORM的java框架,利用该框架我们可以抛弃掉繁琐的sql语句而是

利用Hibernate中Session类的save()方法直接将某个类的对象存到数据库当中,也就是所涉及到sql语句的

那些代码Hibernate帮我们做了。这时候就出现了一个问题,Hibernate怎样知道他要存的某个对象都有什

么属性呢?这些属性都是什么类型呢?想一想,它在向数据库中存储该对象属性时的sql语句该怎么构造

呢?OK,反射的作用此刻就体现出来了!

下面我们以一个例子来进行阐述,比如我们定义了一个User类,这个User类中有20个属性和这些属性的

get和set方法,相应的在数据库中有一个User表,这个User表中对应着20个字段。假设我们从User表中

提取了一条记录,现在需要将这条记录的20个字段的内容分别赋给一个User对象myUser的20个属性,

而Hibernate框架在编译的时候并不知道这个User类,他无法直接调用myUser.getXXX或者

myUser.setXXX方法,此时就用到了反射,具体处理过程如下:

  1. 根据查询条件构造PreparedStament语句,该语句返回20个字段的值;
  2. Hibernate通过读取配置文件得到User类的属性列表list(是一个String数组)以及这些属性的类型;
  3. 创建myUser所属类的Class对象c;c = myUser.getClass();
  4. 构造一个for循环,循环的次数为list列表的长度; 读取list[i]的值,然后构造对应该属性的set方法;

判断list[i]的类型XXX,调用PreparedStament语句中的getXXX(i),进而得到i出字段的值;

将4.2中得到的值作为4.1中得到的set方法的参数,这样就完成了一个字段像一个属性的赋值,

如此循环直至程序运行结束;

如果没有反射难以想象实现这么复杂的功能将会有多么难!

话说回来,反射给我们带来便利的同时也有它自身的缺点,比如性能较低、安全性较低、过程比较复杂等

等,感兴趣的读者也可以在实际工作中再深入研究哦!


相关文章
|
20天前
|
存储 Java
[Java]反射
本文详细介绍了Java反射机制的基本概念、使用方法及其注意事项。首先解释了反射的定义和类加载过程,接着通过具体示例展示了如何使用反射获取和操作类的构造方法、方法和变量。文章还讨论了反射在类加载、内部类、父类成员访问等方面的特殊行为,并提供了通过反射跳过泛型检查的示例。最后,简要介绍了字面量和符号引用的概念。全文旨在帮助读者深入理解反射机制及其应用场景。
13 0
[Java]反射
|
2月前
|
安全 Java 索引
Java——反射&枚举
本文介绍了Java反射机制及其应用,包括获取Class对象、构造方法、成员变量和成员方法。反射允许在运行时动态操作类和对象,例如创建对象、调用方法和访问字段。文章详细解释了不同方法的使用方式及其注意事项,并展示了如何通过反射获取类的各种信息。此外,还介绍了枚举类型的特点和使用方法,包括枚举的构造方法及其在反射中的特殊处理。
62 9
Java——反射&枚举
|
1月前
|
安全 Java 测试技术
🌟Java零基础-反射:从入门到精通
【10月更文挑战第4天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
25 2
|
2月前
|
安全 Java API
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
String常量池、String、StringBuffer、Stringbuilder有什么区别、List与Set的区别、ArrayList和LinkedList的区别、HashMap底层原理、ConcurrentHashMap、HashMap和Hashtable的区别、泛型擦除、ABA问题、IO多路复用、BIO、NIO、O、异常处理机制、反射
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
|
29天前
|
IDE Java 编译器
java的反射与注解
java的反射与注解
16 0
|
2月前
|
Java 程序员 编译器
Java的反射技术reflect
Java的反射技术允许程序在运行时动态加载和操作类,基于字节码文件构建中间语言代码,进而生成机器码在JVM上执行,实现了“一次编译,到处运行”。此技术虽需更多运行时间,但广泛应用于Spring框架的持续集成、动态配置及三大特性(IOC、DI、AOP)中,支持企业级应用的迭代升级和灵活配置管理,适用于集群部署与数据同步场景。
|
2月前
|
存储 安全 Java
扫盲java基础-反射(一)
扫盲java基础-反射(一)
|
2月前
|
Java
扫盲java基础-反射(二)
扫盲java基础-反射(二)
|
4月前
|
安全 Java 测试技术
day26:Java零基础 - 反射
【7月更文挑战第26天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
34 5
|
3月前
|
缓存 安全 Java
【Java 第十篇章】反射
Java 反射技术让程序能在运行时动态获取类信息并操作对象,极大提升了灵活性与扩展性。本文将介绍反射的基本概念、原理及应用,包括如何使用 `Class`、`Field`、`Method` 和 `Constructor` 类进行动态操作。此外,还将探讨反射在动态加载、框架开发与代码测试中的应用场景,并提醒开发者注意性能与安全方面的问题,帮助你更合理地运用这一强大工具。
28 0