IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Java Reflect - 反射的概念 -> 正文阅读

[Java知识库]Java Reflect - 反射的概念

1. 类的加载

当程序主动使用某个类时,如果该类还未被加载到内存中,则系统会通过加载、连接、初始化3个步骤来对该类进行初始化。如果没有意外,JVM将会连续完成这3个步骤,所以有时也把这3个步骤统称为类加载或类初始化。

类加载指的是将类的 class 文件读入内存,并为之创建一个 java.lang.Class 对象,也就是说,当程序中使用任何类时,系统都会为之建立一个java.lang.Class对象。

类加载器负责将.class文件加载到内存中,并为之生成对应的java.lang.Class对象。

① 动态生成.java源文件,并保存在磁盘上

② 把.java源文件编译成.class文件

③ 把编译后的.class文件加载到jvm内存中

④ 根据加载到jvm中的.class字节码文件生成Class类

2. 类初始化的时机

使用反射方式来强制创建某个类或接口对应的 java.lang.Class 对象。例如代码:Class.forName(“Person”),如果系统还未初始化 Person 类,则这行代码将会导致该Person 类被初始化,并返回 Person 类对应的java.lang.Class 对象。

3. 通过反射查看类信息

Java 程序中的许多对象在运行时都会出现两种类型:编译时类型和运行时类型

例如代码:Person p=new Student();,这行代码将会生成一个p变量,该变量的编译时类型为Person,运行时类型为Student;除此之外,还有更极端的情形,程序在运行时接收到外部传入的一个对象,该对象的编译时类型是Object,但程序又需要调用该对象运行时类型的方法。为了解决这些问题,程序需要在运行时发现对象和类的真实信息。

为了解决这个问题,我们有以下两种做法。

  • 第一种做法是假设在编译时和运行时都完全知道类型的具体信息,在这种情况下,我们可以直接先使用 instanceof 运算符进行判断,再利用强制类型转换将其转换成其运行时类型的变量即可。
  • 第二种做法是编译时根本无法预知该对象和类可能属于哪些类,程序只依靠运行时信息来发现该对象和类的真实信息,这就必须使用反射。

反射机制就是指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能够调用它的方法和属性,这种动态获取信息及动态调用对象方法的功能称为java的反射机制。

在这里插入图片描述

反射机制的作用:

每个类被加载之后,系统就会为该类生成一个对应的Class对象,通过该Class对象就可以访问到JVM中的这个类。获取类的属性,方法,构造方法等。

在这里插入图片描述

如上图:定义一个Person类,也就是Person.java(java)文件,这个Person类里面有成员变量,构造方法,成员方法等属性。编译以后会生成一个Person.class字节码文件,当类一旦加载至内存就会产生一个与Person类相关联的Class类对象,这个Class类对象中存放的就是Person类的属性信息,比如成员变量,成员方法,构造方法等。

Class类对象中包含了运行时类的相关信息,包括成员变量,构造方法,成员方法等。通过Class类对象可以获取到该类的构造方法,方法,属性等信息。

在这里插入图片描述

4. 获得Class对象

每个类被加载之后,系统就会为该类生成一个对应的Class对象,通过该Class对象就可以访问到JVM中的这个类。在Java程序中获得Class对象通常有如下3种方式。

  • 使用Class类的forName(String clazzName)静态方法。该方法需要传入字符串参数,该字符串参数的值是某个类的全限定类名(必须添加完整包名)。
  • 调用某个类的class属性来获取该类对应的Class对象。例如,Person.class将会返回Person类对应的Class对象。
  • 调用某个对象的getClass()方法。该方法是java.lang.Object类中的一个方法,所以所有的Java对象都可以调用该方法,该方法将会返回该对象所属类对应的Class对象。

对于第一种方式和第二种方式都是直接根据类来取得该类的Class对象,相比之下,第二种方式有如下两种优势。

  • 代码更安全。程序在编译阶段就可以检查需要访问的Class对象是否存在。
  • 程序性能更好。因为这种方式无须调用方法,所以性能更好。

也就是说,大部分时候我们都应该使用第二种方式来获取指定类的Class对象。但如果我们只有一个字符串,例如“java.lang.String”,若需要获取该字符串对应的Class对象,则只能使用第一种方式,使用Class的forName(String clazzName)方法获取Class对象时,该方法可能抛出一个ClassNotFoundException异常。

public class Main {
    public static void main(String[] args) throws ClassNotFoundException {
        // 方式1
        Class<Person> class1 = Person.class;
        
        // 方式2:包名+类名
        Class<?> class2 = Class.forName("com.example.redislock.reflect.Person");
        
        // 方式3
        Person person = new Person();
        Class<? extends Person> class3 = person.getClass();
    }
}

一旦获得了某个类所对应的Class对象之后,程序就可以调用Class对象的方法来获得该对象和该类的真实信息。Class类提供了大量的实例方法来获取该Class对象所对应类的详细信息。

Class对象可以获得该类里的方法(由Method对象表示)、构造器(由Constructor对象表示)、Field(由 Field 对象表示),这 3个类都位于java.lang.reflect 包下,并实现了java.lang.reflect.Member 接口。程序可以通过Method 对象来执行对应的方法,通过Constructor对象来调用对应的构造器创建实例,能通过Field对象直接访问并修改对象的属性值。

class Solution {
    public static void main(String[] args) throws NoSuchMethodException, NoSuchFieldException {
        // Class类对象
        Class<Person> personClass = Person.class;
        // 构造方法,Constructor类
        Constructor<Person> constructor = personClass.getConstructor(String.class, Integer.class);
        // 方法,Method类
        Method method = personClass.getMethod("toString", String.class);
        // 属性,Field类
        Field field = personClass.getField("name");
    }
}
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-04-30 08:33:07  更:2022-04-30 08:34:50 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 2:12:17-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码