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

相关文章
|
3月前
|
监控 Java API
现代 Java IO 高性能实践从原理到落地的高效实现路径与实战指南
本文深入解析现代Java高性能IO实践,涵盖异步非阻塞IO、操作系统优化、大文件处理、响应式网络编程与数据库访问,结合Netty、Reactor等技术落地高并发应用,助力构建高效可扩展的IO系统。
90 0
|
3月前
|
存储 缓存 安全
深入讲解 Java 并发编程核心原理与应用案例
本教程全面讲解Java并发编程,涵盖并发基础、线程安全、同步机制、并发工具类、线程池及实际应用案例,助你掌握多线程开发核心技术,提升程序性能与响应能力。
117 0
|
3月前
|
人工智能 前端开发 安全
Java开发不可不知的秘密:类加载器实现机制
类加载器是Java中负责动态加载类到JVM的组件,理解其工作原理对开发复杂应用至关重要。本文详解类加载过程、双亲委派模型及常见类加载器,并介绍自定义类加载器的实现与应用场景。
186 4
|
3月前
|
人工智能 安全 Java
Go与Java泛型原理简介
本文介绍了Go与Java泛型的实现原理。Go通过单态化为不同类型生成函数副本,提升运行效率;而Java则采用类型擦除,将泛型转为Object类型处理,保持兼容性但牺牲部分类型安全。两种机制各有优劣,适用于不同场景。
96 24
|
4月前
|
存储 缓存 Java
我们来详细讲一讲 Java NIO 底层原理
我是小假 期待与你的下一次相遇 ~
154 2
|
4月前
|
XML JSON Java
Java 反射:从原理到实战的全面解析与应用指南
本文深度解析Java反射机制,从原理到实战应用全覆盖。首先讲解反射的概念与核心原理,包括类加载过程和`Class`对象的作用;接着详细分析反射的核心API用法,如`Class`、`Constructor`、`Method`和`Field`的操作方法;最后通过动态代理和注解驱动配置解析等实战场景,帮助读者掌握反射技术的实际应用。内容翔实,适合希望深入理解Java反射机制的开发者。
320 13
|
4月前
|
算法 Java 索引
说一说 Java 并发队列原理剖析
我是小假 期待与你的下一次相遇 ~
|
4月前
|
安全 Java 编译器
JD-GUI,java反编译工具及原理: JavaDecompiler一个Java反编译器
Java Decompiler (JD-GUI) 是一款由 Pavel Kouznetsov 开发的图形化 Java 反编译工具,支持 Windows、Linux 和 Mac Os。它能将 `.class` 文件反编译为 Java 源代码,支持多文件标签浏览、高亮显示,并兼容 Java 5 及以上版本。JD-GUI 支持对整个 Jar 文件进行反编译,可跳转源码,适用于多种 JDK 和编译器。其原理基于将字节码转换为抽象语法树 (AST),再通过反编译生成代码。尽管程序可能带来安全风险,但可通过代码混淆降低可读性。最新版修复了多项识别错误并优化了内存管理。
1947 1
|
4月前
|
存储 算法 安全
Java中的对称加密算法的原理与实现
本文详细解析了Java中三种常用对称加密算法(AES、DES、3DES)的实现原理及应用。对称加密使用相同密钥进行加解密,适合数据安全传输与存储。AES作为现代标准,支持128/192/256位密钥,安全性高;DES采用56位密钥,现已不够安全;3DES通过三重加密增强安全性,但性能较低。文章提供了各算法的具体Java代码示例,便于快速上手实现加密解密操作,帮助用户根据需求选择合适的加密方案保护数据安全。
346 58