Java反射机制及原理

简介: 本文介绍了Java反射机制的基本概念、使用方法及其原理。反射在实际项目中比代理更常用,掌握它可以提升编程能力并理解框架设计原理。文章详细讲解了获取Class对象的四种方式:对象.getClass()、类.class、Class.forName()和类加载器.loadClass(),并分析了Class.forName()与ClassLoader的区别。此外,还探讨了通过Class对象进行实例化、获取方法和字段等操作的具体实现。最后从JVM类加载机制角度解析了Class对象的本质及其与类和实例的关系,帮助读者深入理解Java反射的工作原理。

前言

相比于Java的代理,在实际项目中反射其实要更常用的多,所以学好反射不仅是能懂得框架设计的原理,更能在日常工作开发中提高编程能力

使用

要使用Java反射首先要得到的就是Java的Class对象,这很重要,使用反射无非就是要获取到对应的类的Class对象,因为只有先获取到Class对象,你才能获取到类的实例,静态方法,构造方法,非静态方法等。

那么如何获取Class对象呢?获取Class对象的方式又有哪几种?

获取Class对象的四种方式:

  • (对象.getClass()), 通过对象实例获取Class对象,如下:

js

体验AI代码助手

代码解读

复制代码

Person person = new Person();
Class personClass = person.getClass()

这种一般没什么啥用,因为一般而言使用反射就是为了获取类的class对象再获取类的实例,方法,这种方式是在你都已经知道Person类的前提下了。

  • 类.class: 通过类来获取Class对象,如下

js

体验AI代码助手

代码解读

复制代码

Class personClass = Person.class

这种跟上一种一样有些鸡肋,上一个的使用前提是已知对象,这一个的使用前提是已知类。

  • 通过 Class.forName() 传入类的路径获取:

js

体验AI代码助手

代码解读

复制代码

Class testClass = Class.forName("com.xx.Test");

这种是最常用的,前提是知道类路径

  • 通过类加载器xxxClassLoader.loadClass()获取

js

体验AI代码助手

代码解读

复制代码

Class testClass = ClassLoader.loadClass("com.xx.Test");

类加载器有四种,启动类加载器,扩展类加载器,应用类加载器,自定义加载器,这种方式的前提和上一种一样,都是要先知道类路径。

Class.forName()和ClassLoader 两种获取class对象方式的区别:

回顾下类加载时机的知识,我们知道虚拟机规范严格规定了有且只有 5 种情况必须立即对类进行初始化,其中一种就是使用反射对类进行调用时,具体的话就是使用Class.forName()获取class对象的反射调用方式会触发类初始化,因为Class.forName在加载类的同时会执行该类的静态代码块,因此具有类似于静态初始化的效果。

类加载和类初始化是两个概念,按照顺序而言,一个类要经过三个阶段,类加载,类初始化,类实例化。 会触发类初始化的类加载时机只有5种情况,这5种情况称为主动引用,其他的称为被动引用。但这5种情况中并不包含类加载器加载类的情况,所以第一点区别就是:

  • Class.forName()会触发类的初始化,而ClassLoader加载类只是单纯的加载类
  • 其他的区别就是使用方式的区别了,Class.forName得指定类的全限定名,而ClassLoader加载类的方式更灵活

反射的一些操作

获取到Class对象之后我们可以通过Class对象拿到什么呢?假设我们已经通过上述四种方式之一获取到Class对象。

  • 可以获取类的对象实例

js

体验AI代码助手

代码解读

复制代码

Class testClass = ClassLoader.loadClass("com.xx.Test");
Test testObject = (Test)testClass.newInstance();
  • 可以获取类的所有定义的方法

js

体验AI代码助手

代码解读

复制代码

Class testClass = ClassLoader.loadClass("com.xx.Test");
Method[] methods = testClass.getDeclaredMethods();

甚至可以获取指定方法并调用,获取私有方法,获取构造方法

  • 可以获得类的属性比如字段

js

体验AI代码助手

代码解读

复制代码

Class testClass = ClassLoader.loadClass("com.xx.Test");
Field field = testClass.getDeclaredField("name");

原理

提到反射我们老说Class对象,Class对象,那么Class对象到底是什么,与我们代码中定义的类和生成的实例又有什么关系?

我们都知道Java是编译型语言,先编译后运行,所以就会有编译期和运行期。

学过JVM类加载机制肯定知道Java类生命周期的第一个阶段就是加载,而在这个阶段虚拟机做的第三件事即是为这个类生成java.lang.Class对象,所以这个Class对象硬要有所指,那就是类生成的Class字节码文件!而类的加载是在运行期,所以我们说JAVA反射机制是在运行状态中。所以有些人觉得为什么Class对象那么神奇能获取到各种方法和属性,但其实本来就是Java代码中的类生成的class文件,所以能获取到类的各种信息。


转载来源:https://juejin.cn/post/6982234402499592205

相关文章
|
2月前
|
人工智能 Java 关系型数据库
Java——SPI机制详解
SPI(Service Provider Interface)是JDK内置的服务提供发现机制,主要用于框架扩展和组件替换。通过在`META-INF/services/`目录下定义接口实现类文件,Java程序可利用`ServiceLoader`动态加载服务实现。SPI核心思想是解耦,允许不同厂商为同一接口提供多种实现,如`java.sql.Driver`的MySQL与PostgreSQL实现。然而,SPI存在缺陷:需遍历所有实现并实例化,可能造成资源浪费;获取实现类方式不够灵活;多线程使用时存在安全问题。尽管如此,SPI仍是Java生态系统中实现插件化和模块化设计的重要工具。
|
2月前
|
存储 安全 Java
【高薪程序员必看】万字长文拆解Java并发编程!(4-1):悲观锁底层原理与性能优化实战
目录4. JVM字节码文件4.1. 字节码文件-组成4.1.1. 组成-基础信息4.1.1.1. 基础信息-魔数4.1.1.2. 基础信息-主副版本号4.1.2. 组成-常量池4.1.3. 组成-方法4.1.3.1. 方法-工作流程4.1.4. 组成-字段4.1.5. 组成-属性4.2. 字节码文件-查看工具4.2.1. javap4.2.2. jclasslib4.2.3. 阿里Arthas
46 0
|
2月前
|
存储 缓存 Java
【高薪程序员必看】万字长文拆解Java并发编程!(5):深入理解JMM:Java内存模型的三大特性与volatile底层原理
JMM,Java Memory Model,Java内存模型,定义了主内存,工作内存,确保Java在不同平台上的正确运行主内存Main Memory:所有线程共享的内存区域,所有的变量都存储在主存中工作内存Working Memory:每个线程拥有自己的工作内存,用于保存变量的副本.线程执行过程中先将主内存中的变量读到工作内存中,对变量进行操作之后再将变量写入主内存,jvm概念说明主内存所有线程共享的内存区域,存储原始变量(堆内存中的对象实例和静态变量)工作内存。
95 0
|
2月前
|
存储 安全 Java
深入探究Java中ThreadLocal的工作原理和用途
总结起来,ThreadLocal是Java多线程编程中一个非常有用的工具,通过为每个线程分配独立的变量副本,实现线程隔离,避免资
70 9
|
2月前
|
设计模式 人工智能 安全
AQS:Java 中悲观锁的底层实现机制
AQS(AbstractQueuedSynchronizer)是Java并发包中实现同步组件的基础工具,支持锁(如ReentrantLock、ReadWriteLock)和线程同步工具类(如CountDownLatch、Semaphore)等。Doug Lea设计AQS旨在抽象基础同步操作,简化同步组件构建。 使用AQS需实现`tryAcquire(int arg)`和`tryRelease(int arg)`方法以获取和释放资源,共享模式还需实现`tryAcquireShared(int arg)`和`tryReleaseShared(int arg)`。
104 32
AQS:Java 中悲观锁的底层实现机制
|
2月前
|
Java 区块链 网络架构
酷阿鲸森林农场:Java 区块链系统中的 P2P 区块同步与节点自动加入机制
本文介绍了基于 Java 的去中心化区块链电商系统设计与实现,重点探讨了 P2P 网络在酷阿鲸森林农场项目中的应用。通过节点自动发现、区块广播同步及链校验功能,系统实现了无需中心服务器的点对点网络架构。文章详细解析了核心代码逻辑,包括 P2P 服务端监听、客户端广播新区块及节点列表自动获取等环节,并提出了消息签名验证、WebSocket 替代 Socket 等优化方向。该系统不仅适用于农业电商,还可扩展至教育、物流等领域,构建可信数据链条。
|
3月前
|
存储 Java 编译器
Java 中 .length 的使用方法:深入理解 Java 数据结构中的长度获取机制
本文深入解析了 Java 中 `.length` 的使用方法及其在不同数据结构中的应用。对于数组,通过 `.length` 属性获取元素数量;字符串则使用 `.length()` 方法计算字符数;集合类如 `ArrayList` 采用 `.size()` 方法统计元素个数。此外,基本数据类型和包装类不支持长度属性。掌握这些区别,有助于开发者避免常见错误,提升代码质量。
204 1
|
4月前
|
缓存 Dubbo Java
理解的Java中SPI机制
本文深入解析了JDK提供的Java SPI(Service Provider Interface)机制,这是一种基于接口编程、策略模式与配置文件组合实现的动态加载机制,核心在于解耦。文章通过具体示例介绍了SPI的使用方法,包括定义接口、创建配置文件及加载实现类的过程,并分析了其原理与优缺点。SPI适用于框架扩展或替换场景,如JDBC驱动加载、SLF4J日志实现等,但存在加载效率低和线程安全问题。
144 7
理解的Java中SPI机制
|
4月前
|
存储 缓存 人工智能
【原理】【Java并发】【synchronized】适合中学者体质的synchronized原理
本文深入解析了Java中`synchronized`关键字的底层原理,从代码块与方法修饰的区别到锁升级机制,内容详尽。通过`monitorenter`和`monitorexit`指令,阐述了`synchronized`实现原子性、有序性和可见性的原理。同时,详细分析了锁升级流程:无锁 → 偏向锁 → 轻量级锁 → 重量级锁,结合对象头`MarkWord`的变化,揭示JVM优化锁性能的策略。此外,还探讨了Monitor的内部结构及线程竞争锁的过程,并介绍了锁消除与锁粗化等优化手段。最后,结合实际案例,帮助读者全面理解`synchronized`在并发编程中的作用与细节。
210 8
【原理】【Java并发】【synchronized】适合中学者体质的synchronized原理
|
4月前
|
消息中间件 Java 应用服务中间件
JVM实战—1.Java代码的运行原理
本文介绍了Java代码的运行机制、JVM类加载机制、JVM内存区域及其作用、垃圾回收机制,并汇总了一些常见问题。
JVM实战—1.Java代码的运行原理