java每日一记 —— 谈谈反射

这应该是基础吧

  • 1.先来说点前置知识:类的加载机制
  • 2.以自己的方式来谈反射的概念
  • 3.获取class的三种方式
    • 3.1.通过已知的类型获取class
    • 3.2.通过实例对象获取class
    • 3.3.通过Class.forName获取全路径指定类名的class
  • 4.整理了一下API:坦言说🪡累
  • 5.现场玩一把
  • 6.反射机制应用的场景

本篇代码在jdk11中测试通过

1.先来说点前置知识:类的加载机制

1.博主是这样理解的:Java 类的加载机制就是将类从字节码转换为运行时实例的过程(好吧!!!我是来搞笑的😱😱😱😱)

2.回归正题:Java 类的加载机制是一个动态过程,由 Java 虚拟机 (JVM) 自动完成

一般流程如下:

  • 加载:将类从磁盘或其他数据源加载到 JVM 内存中
  • 验证:确保类有效,并符合语义要求
  • 准备:给类变量分配内存,并设置类变量的默认值
  • 解析:将常量池中的符号引用替换为直接引用
  • 初始化:给类变量赋值,并调用类构造函数

来一张小破图:
在这里插入图片描述

开个小玩笑:我怎么越看越像上高速公路的一个过程??
加载?好像是从四面八方来的车要进入收费站入口
验证?怎么看都是收费站的要判断你是否符合上高速的要求啊?
准备?这个有点像给你发的通行卡中记录了你的信息?
解析?你进入高速匝道后的指示牌给你直接引用到正确的路线?
初始化?这个不就是进入高速后给车加油门,并且打开我们的bgm?

3.总结一下:其实吧每个阶段都涉及 JVM 内部的操作,这只是为了确保类的安全性和可用性。因此,在运行时可以通过反射轻松访问 Java 类的信息

特别注意:今天的主角不是类加载机制,这些只是根据经验写了点

2.以自己的方式来谈反射的概念

1.定义:Java反射是一种允许我们在程序运行时访问和修改其自身行为的技术。它允许我们在运行时检查和修改程序的行为,而不需要重新编译或启动程序

2.面试时我如果按照定义说,面试官肯定肯说我背了八股,所以我用自己的理解说下反射的定义吧:

  • 通俗说法:Java反射是一种能够在运行时检查和修改程序自身行为的能力。它可以让我们在不重新编译或重启应用程序的情况下,对程序的行为进行更改。例如,我们可以使用反射来动态地改变一个类的方法或者字段值,或者动态地创建和访问类的实例

我来以生活的方式来说:

首先,让我们从一个简单的例子开始。假设我们正在准备一顿晚餐,并且想要制作一道美味的意大利面。在烹饪过程中,我们需要了解各种食材的特性,比如面条需要煮多久才能达到最佳口感,番茄酱应该如何调配等等。这就像是我们在编程时需要了解每个类和方法的功能一样。

现在,想象一下如果我们有一本食谱,它不仅告诉我们如何做菜,还告诉我们可以用哪些不同的食材来替代原本的食材,甚至还可以告诉我们每种食材有哪些未知的特性和用途。这就是Java反射的概念

Java反射允许我们在运行时检查和修改程序的行为。就像我们的食谱一样,它提供了一种方式来查看和操作代码的各种元素,如类、接口、字段和方法。我们可以利用这些信息来创建新的对象、调用方法、改变字段值等

3.new 和反射的对比

在这里插入图片描述
4.java相关类介绍

类名描述
Class<T>代表类的实体,在运行的Java应用程序中表示类或者接口
Field类的成员变量(成员变量也称为类的属性)
Method类的方法
Constructor<T>类的构造方法

3.获取class的三种方式

3.1.通过已知的类型获取class

1.上代码

public Class<User> getUser01(){
    Class<User> clazz = User.class;
    return clazz;
}

2.运行结果
在这里插入图片描述

3.2.通过实例对象获取class

1.上代码

public Class<User> getUser02(){
    User user = new User();
    Class<?> clazz = user.getClass();
    return (Class<User>)clazz;
}

2.运行结果
在这里插入图片描述

3.3.通过Class.forName获取全路径指定类名的class

1.上代码

public static Class<User> getUser03()throws ClassNotFoundException{
    Class<?> clazz = Class.forName("com.andy.fan_she.pojo.User");
    return (Class<User>)clazz;
}

2.运行结果
在这里插入图片描述

4.整理了一下API:坦言说🪡累

1.Class常用操作方法

// 获取所有的构造方法 (private和public都可以)
public Constructor<?>[] getDeclaredConstructors()

// 获取特定的构造方法 (private和public都可以)
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
   
// 获取类的父类
public native Class<? super T> getSuperclass()

// 获取类实现的接口
private Class<?>[] getInterfaces(boolean cloneArray)

// 获取在类内定义的内部类或接口
public Class<?>[] getDeclaredClasses()

// 获取所有的方法
public Method[] getDeclaredMethods() throws SecurityException

// 根据方法名和参数获得特定的方法
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)

// 获取类型的定义的所有属性
public Field[] getFields()

// 根据属性命名获得特定的Field
public Field getField(String name)

2.Method常用的操作方法

// 获得方法的放回类型
public Class<?> getReturnType()

// 获得方法的传入参数类型
public Class<?>[] getParameterTypes()

// obj是实例对象,args是方法,反过来由Method控制对象的方法调用
public Object invoke(Object obj, Object... args)

3.Field常用的操作方法

// 属性与obj相等则返回true
public boolean equals(Object obj)

// 获得obj中对应的属性值
public Object get(Object obj)

// 设置obj中对应属性值
public void set(Object obj, Object value)

4.Constructor

// 根据传递的参数创建类的对象:initargs 构造方法参数
public T newInstance(Object... initargs) 

⚠️注意啦!!!注意啦!!!⚠️

  • 从Java 11开始,newInstance()方法已被弃用,因为它存在一定的安全风险。现在推荐使用Class.getDeclaredConstructor().newInstance()的方式来替代

  • 在Java 11及更高版本中,如果没有显式声明默认构造函数,那么默认情况下是不会生成无参数构造函数的。因此,如果要调用newInstance()方法,则需要确保类具有可访问的无参数构造函数

5.现场玩一把

来个测试对象类

/**
 * @author Andy
 * @version 0.0.1
 */
public class User implements Serializable {

    private Integer id;

    private String username;
    
	private string password;

    private String password;
    
    public User(Integer id, String username, String password) {
        this.id = id;
        this.username = username;
        this.password = password;
    }

    ...getter/setter

}

1.根据class创建对象

public User getUser01() throws Exception {
	Class<User> clazz = User.class;
    Constructor<User> constructor = clazz.getConstructor(Integer.class, String.class, String.class);
    constructor.setAccessible(true);
    User user = constructor.newInstance(1, "andy", "123456");
    return user;
}

2.由class获取Field,并操作实例的属性

public static User getUser02() throws Exception{
    Class<User> clazz = User.class;
    Constructor<User> constructor = clazz.getConstructor(Integer.class, String.class, String.class);
    constructor.setAccessible(true);
    User user = constructor.newInstance(1, "andy", "123456");
    // 主要是这块逻辑
    Field declaredField = clazz.getDeclaredField("id");
    declaredField.setAccessible(true);
    declaredField.set(user, 2);
    return user;
}

3.由class获取Method,并反射调用实例方法

// 在pojo中加入:
public void getTestUser(String name){
    System.out.println("测试反射方法:" + name);
}

// 测试方法:
public static void getUser03() throws Exception {
    Class<User> clazz = User.class;
    Constructor<User> constructor = clazz.getConstructor(Integer.class, String.class, String.class);
    constructor.setAccessible(true);
    User user = constructor.newInstance(1, "andy", "123456");
    //主要逻辑
    Method declaredMethod = clazz.getDeclaredMethod("getTestUser", String.class);
    declaredMethod.setAccessible(true);
    declaredMethod.invoke(user, "Andy测试");
}

6.反射机制应用的场景

  • 动态拓展:假设有同一组类是实现相同的接口,并且类的加载方式不限制。当我们需要那种具体类实现的功能时,只需加载.class文件,并获取对应的Class对象。可以由Class或者Constructor实例化对象instance;根据接口定义,可以获取Class里的某一方法Method,并配合instance反射调用功能方法
  • Spring的IOC就是基于反射机制实现
  • JDK的动态代理

博主记得之前写过一个动态代理的博客,今天特地的跑去看了下🪡的是反射机制。有兴趣的可以看下:https://blog.csdn.net/weixin_44702984/article/details/130278266?spm=1001.2014.3001.5502

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/160810.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

利用X6 制作一个简单的流程图工具

介绍 项目模版使用 我自己基于 arco-design 封装的一个 B 端项目模版 。 地址&#xff1a;https://github.com/duKD/antv-x6-org 运用 antv/X6 &#xff1a; https://x6.antv.antgroup.com/ 来实现 一个简单的流程图工具 项目预览&#xff1a; 功能 支持框选 alt鼠标左键…

记一次用jlink调试正常,不进入调试就不能运行的情况

一、概述 我开机会闪烁所有指示灯&#xff0c;但是重新上电时&#xff0c;指示灯并没有闪烁&#xff0c;就像"卡死"了一样。 使用jlink的swd接口进行调试&#xff0c;需要多点几次运行才能跳转到main函数里面。 调试模式第一次点击运行&#xff0c;暂停查看函数堆栈…

iframe父子页面通信相互调用传递参数多个postMessage

效果 如何运行 父页面代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title>…

PyTorch DataLoader整理函数详解【collate_fn】

DataLoader 是 PyTorch 中最常用的类之一。 而且&#xff0c;它是你首先学习的内容之一。 该类有很多参数&#xff0c;但最有可能的是&#xff0c;你将使用其中的大约三个参数&#xff08;dataset、shuffle 和 batch_size&#xff09;。 今天我想解释一下 collate_fn 的含义—根…

【开源】基于JAVA的校园失物招领管理系统

项目编号&#xff1a; S 006 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S006&#xff0c;文末获取源码。} 项目编号&#xff1a;S006&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、研究内容2.1 招领管理模块2.2 寻物管理模块2.3 系…

Linux shell编程学习笔记26:stty(set tty)

之前我们探讨了Linux中的tty&#xff0c;tty命令的主要功能是显示当前使用的终端名称。 如果我们想进一步对tty进行设置&#xff0c;就要用到stty。 stty的功能&#xff1a;显示和修改终端特性&#xff08;Print or change terminal characteristics&#xff09;。 1 stty -…

设置 SSH 主机 ***: (details) 连接到 VS Code Server - 重试 2

VS Code Server 一直重试输入密码 问题描述解决方法1、打开命令面板Ctrl shift p2、在输入框中输入Kill3、在弹出框中选择一直重复输入密码的服务器主机号&#xff0c;输入密码即可成功。 问题描述 VSCode 在使用插件 Remote - SSH 连接远程服务器时总是会遇到各种问题&#…

电脑软件:推荐一款非常实用的固态硬盘优化工具

目录 一、软件简介 二、工作原理 三、功能介绍 3.1、优化SSD设置 3.2、查看驱动器信息 3.3、查看SMART数据 3.4、停用Windows事件日志记录 3.5、禁用Windows碎片整理 3.6、时间戳停用 3.7、禁用引导文件的碎片整理 3.8、关闭短名称 四、使用教程 4.1 安装说明 4.…

猜数字优化版(带进度条)

其实就是加了个动态进度条显示加载游戏的流程&#xff0c;这样看上去是不是更有big了hhhh #include<windows.h> #include<iostream> #include<ctime> using namespace std; void menu() {printf("1.开始游戏\n");printf("0.退出游戏\n")…

CTFhub-RCE-综合过滤练习

%0a、%0d、%0D%0A burp 抓包 修改请求为 POST /?127.0.0.1%0als 列出当前目录 返回包 http://challenge-135e46015a30567b.sandbox.ctfhub.com:10800/?ip127.0.0.1%0acd%09*here%0ac%27a%27t%09* _311632412323588.php

基于和声算法优化概率神经网络PNN的分类预测 - 附代码

基于和声算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于和声算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于和声优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神经网络的光滑…

java+ 如何动态配置业务规则组

思路 1. 实现在页面上的动态配置规则组&#xff08;2张数据表枚举类serviceimplaction&#xff09; 2. 从数据库中表staffmoverules&#xff08;规则明细表&#xff09;或者staffmovetyperule&#xff08;规则组表&#xff09; &#xff0c;根据传入类型&#xff0c;取出规则编…

【开源】基于JAVA的快递管理系统

项目编号&#xff1a; S 007 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S007&#xff0c;文末获取源码。} 项目编号&#xff1a;S007&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、研究内容2.1 数据中心模块2.2 快递类型模块2.3 快…

YOLOv8-Seg改进:渐近特征金字塔网络(AFPN)

🚀🚀🚀本文改进:AFPN通过融合两个相邻的Low-Level特征来启动的,并渐进地将High-Level特征纳入融合过程,提升分割能力。 🚀🚀🚀AFPN小目标分割首选,暴力涨点 🚀🚀🚀YOLOv8-seg创新专栏:http://t.csdnimg.cn/KLSdv 学姐带你学习YOLOv8,从入门到创新,轻…

c++中的String

文章目录 String定义对象的方式成员函数operatorbegin/endsizecapacityreserversizeoperator/append/push_backoperator[]/at String String是一个类模版&#xff0c;可以定义一个字符/字符串对象。 字符顺序表 定义对象的方式 定义方式有很多重要的就这几种 string s1;stri…

配置环境-insightface-torch

1. 创建环境&#xff1a;conda create -n insightface2 python3.8 2.安装pytorch: 我的cuda 是 11.3 然后进入 pytorch 官网查找对应cuda 版本 pytorch 安装 建议使用 pip # CUDA 11.3 conda install pytorch1.12.1 torchvision0.13.1 torchaudio0.12.1 cudatoolkit11.3 -…

UE5 C++报错:is not currently enabled for Live Coding

解决办法&#xff1a; 再次打开项目&#xff0c;以此法打开&#xff1a;

贝叶斯AB测试

AB测试是用来评估变更效果的有效方法&#xff0c;但很多时候会运行大量AB测试&#xff0c;如果能够在测试中复用之前测试的结果&#xff0c;将有效提升AB测试的效率和有效性。原文: Bayesian AB Testing[1] 随机实验&#xff0c;又称AB测试&#xff0c;是行业中评估因果效应的既…

Windos操作系统下的Zookeeper安装图文教程

凯哥已经准备好最新版本3.9.1且已经配置好了。既获取到配置好的。 获取到凯哥准备的安装后&#xff0c;只需要修改一下配置。将解压包解压后&#xff0c;找到conf文件&#xff0c;里面有个zoo.cfg配置文件。如下图&#xff1a; 下载后conf文件夹内容 打开zoo.cfg配置文件后&a…

Vue项目

使用vs打开Vue项目 运行&#xff1a; 终端命令&#xff1a; npm run serve初次打开的是App.vue页面 修改服务器端口 vue.config.js const { defineConfig } require(vue/cli-service) module.exports defineConfig({transpileDependencies: true,devServer: { //增…