目录

    • 一、反射
      • 1.JDK,JRE,JVM的关系
      • 2.什么是反射
      • 3. 三种获取Class对象(类的字节码)的方式
      • 4.Class常用方法
      • 5. 获取类的构造器
      • 6.反射获取成员变量&使用
      • 7.反射获取成员方法
      • 8.综合例子

一、反射

1.JDK,JRE,JVM的关系

三者是Java运行环境的核心组成部分,从包含关系上看:JDK 包含JRE包含JVM,具体作用如下:

  • JDK(Java Development Kit,Java开发工具包)
    是Java开发的工具集合,包含 JRE + 编译器(javac)、调试工具(jdb)、文档工具(javadoc)等开发必需的工具。如果需要编写、编译Java程序,必须安装JDK。

  • JRE(Java Runtime Environment,Java运行时环境)
    运行Java程序的最小环境,包含 JVM + 运行Java程序必需的类库(如java.lang包等)。如果只需要运行Java程序(如 .class 或 .jar 文件),安装JRE即可。

  • JVM(Java Virtual Machine,Java虚拟机)
    是运行Java字节码的虚拟计算机,负责将字节码翻译成具体操作系统可执行的机器码。它是Java“一次编写,到处运行”(跨平台)的核心,不同操作系统需要安装对应的JVM实现。

  • 字节码的运行过程:

    编译阶段:开发者编写的Java源代码( .java 文件),通过JDK中的编译器(javac)编译成字节码文件( .class 文件),字节码是一种与平台无关的二进制指令。

    类加载:运行时,JVM的类加载器(ClassLoader)将 .class 文件(磁盘或者其他地方)加载到JVM内存中。

    字节码执行:JVM中的执行引擎(如解释器或即时编译器JIT)将字节码翻译成当前操作系统可识别的机器码,最终由操作系统执行机器码,完成程序功能。

    简单来说,字节码是Java跨平台的“中间语言”,通过JVM在不同系统上的适配,实现了“一次编译,到处运行”。

2.什么是反射

​ 反射是允许程序在运行期间可以获取类的类型( Class 对象(字节码对象)),成员变量,方法并可以动态的创建对象,访问属性,调用方法之类的操作。例如在往spring容器中注入一个bean对象,就是通过指定bean的class类型,然后spring框架在启动的时候就可以创建出这个bean对象。

具体:

1.“获取类的类型” 的本质:
这里的 “类型” 其实就是 Class 对象(字节码对象),它是反射的入口。比如 Spring 中指定 class="com.example.User",框架会通过 Class.forName("com.example.User") 获取 Class 对象,进而操作这个类。
2.动态性的核心体现:
你提到的 “动态创建对象、访问属性、调用方法”,核心是不需要在编译期写死具体类名或方法名。例如 Spring 配置文件中改一下 class 属性的值,无需重新编译代码,就能创建不同的对象,这就是反射动态性的价值。
3.框架中的典型流程:
以 Spring 注入 Bean 为例,反射的具体步骤是:
读取配置文件中的 class 属性(全类名);
通过 Class.forName() 获取 Class 对象;
通过 Constructor.newInstance() 动态创建实例(反射创建对象);
若有属性注入,再通过 Field.set() 动态设置属性值(反射操作属性)。

3. 三种获取Class对象(类的字节码)的方式

方法一:直接通过一个 class 的静态变量 class 获取:

Class cls = String.class;

方法二:如果我们有一个实例变量,可以通过该实例变量提供的 getClass () 方法获取:

String s = "Hello";
Class cls = s.getClass();

方法三:如果知道一个 class 的完整类名,可以通过静态方法 Class.forName () 获取:

Class cls = Class.forName("java.lang.String");

注意:因为 Class 实例在 JVM 中是唯一的,所以,上述方法获取的 class 实例是同一个实例。可以用 == 或hashcode()比较实例。

eg:

public class Test2 {public static void main(String[] args) throws ClassNotFoundException {Class  class1 = Class.forName("第二周.day3.Order");Class<Order> class2 = Order.class;Class class3 = new Order().getClass();System.out.println(class1.hashCode());//2003749087System.out.println(class2.hashCode());//2003749087System.out.println(class3.hashCode());//2003749087}
}
class  Order{static {System.out.println("静态代码块中Order已经执行!!!");}
}

4.Class常用方法

获取父类的Class,获取实现接口的Class:

public class Test3 {public static void main(String[] args) {Class<String> stringClass = String.class;System.out.println("完全限定类名:" + stringClass.getName());System.out.println("完全限定类名:" + stringClass.getTypeName());System.out.println("仅包含类名:" + stringClass.getSimpleName());System.out.println("所在的包名:" + stringClass.getPackage());// 获取父类的 Class 对象//String 类继承自 java.lang.Object,所以返回 Object 类的 Class 实例Class<? super String> superclass = stringClass.getSuperclass();System.out.println("父类:" + superclass);//  获取类实现的接口(String 类实现了多个接口,如 Serializable、Comparable等)Class[] interfaces = stringClass.getInterfaces();for (Class anInterface : interfaces) {System.out.println("接口:" + anInterface);}}
}

判断继承关系:

public class Test7 {public static void main(String[] args) {// instanceof 关键字:判断对象是否是某个类型的实例(被注释示例)// Integer n = 2;// System.out.println(n instanceof Integer); // true(自身类型)// System.out.println(n instanceof Number);  // true(父类)// isAssignableFrom:判断类型B能否赋值给类型A(Class类方法)// 1. Integer能否赋值给Integer(自身类型)System.out.println(Integer.class.isAssignableFrom(Integer.class)); // true// 2. Number能否赋值给Integer(父类→子类,不成立)System.out.println(Integer.class.isAssignableFrom(Number.class));  // false// 3. Integer能否赋值给Number(子类→父类,成立)System.out.println(Number.class.isAssignableFrom(Integer.class));  // true}
}

判断Class的类型:

public class Test3 {public static void main(String[] args) {// 获取不同类型的Class对象Class clz1 = String.class;        // 普通类Class clz2 = DayOfWeek.class;     // 枚举类Class clz3 = String[].class;      // 数组类型Class clz4 = List.class;          // 接口// 调用info方法打印类信息info(clz1);info(clz2);info(clz3);info(clz4);}// 打印类的基本类型信息public static void info(Class clazz) {System.out.println("类信息:" + clazz);System.out.println("是否是接口? " + clazz.isInterface());System.out.println("是否是枚举? " + clazz.isEnum());System.out.println("是否是数组? " + clazz.isArray());System.out.println("---------------------"); // 分隔线}
}

5. 获取类的构造器

过字节码对象获取构造器,并使用构造器创建对象。

在这里插入图片描述

get:获取
Declared: 有这个单词表示可以获取任意一个,没有这个单词表示只能获取一个public修饰的
Constructor: 构造方法的意思
后缀s: 表示可以获取多个,没有后缀s只能获取一个

反射获取构造器的作用:初始化对象并返回

在这里插入图片描述

eg:

package 第二周.day3;import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;public class Test5 {public static void main(String[] args)throws NoSuchMethodException,  // 当找不到指定构造方法时抛出InvocationTargetException,  // 构造方法执行过程中抛出异常时包装此异常InstantiationException,  // 当类是抽象类或接口等无法实例化时抛出IllegalAccessException  // 构造方法访问权限不足时抛出{// 获取Animal类的Class对象// Class对象是反射的核心,包含了类的所有元信息(构造方法、方法、字段等)Class clazz = Animal.class;// 获取指定参数列表的构造方法// getConstructor()方法参数为构造方法的参数类型对应的Class对象Constructor constructor0 = clazz.getConstructor(); // 获取无参构造方法Constructor constructor1 = clazz.getConstructor(int.class); // 获取接收int类型参数的构造方法Constructor constructor2 = clazz.getConstructor(int.class, double.class); // 获取接收int和double类型参数的构造方法// 通过反射获取的Constructor对象创建Animal实例// newInstance()方法的参数为实际传递给构造方法的参数值System.out.println("===========");Object o1 = constructor0.newInstance();  // 调用无参构造方法创建实例// 打印创建的对象(默认调用Object类的toString()方法,输出类名@哈希码)System.out.println(o1);System.out.println("===========");Object o2 = constructor1.newInstance(23);  // 调用int参数的构造方法,传入23System.out.println(o2);System.out.println("===========");Object o3 = constructor2.newInstance(23, 3.14);  // 调用int和double参数的构造方法,传入23和3.14System.out.println(o3);}
}class Animal {// 静态代码块:在类加载阶段执行,且只执行一次// 用于验证类加载的时机(当获取Class对象时会触发类加载)static {System.out.println("Animal类被加载!!!!");}// 无参构造方法public Animal() {System.out.println("无参构造方法被执行。");}// 接收int类型参数的构造方法public Animal(int a) {System.out.println("有参构造方法被执行:a = " + a);}// 接收int和double类型参数的构造方法public Animal(int a, double b) {System.out.println("有参构造方法被执行:a = " + a + ",b = " + b);}
}

6.反射获取成员变量&使用

在Class类中提供了获取成员变量的方法:

在这里插入图片描述

再次强调一下设置值、获取值的方法时Filed类的需要用Filed类的对象来调用,而且不管是设置值、还是获取值,都需要依赖于该变量所属的对象。代码如下:

设置值:

import java.lang.reflect.Field;// 演示 Java 反射机制:通过 Class 对象操作 Employee 类的私有成员
public class Test8 {public static void main(String[] args) throws Exception {// ========== 1. 获取 Class 对象(反射入口) ==========// 方式:类名.class,获取 Employee 类的字节码元数据Class clazz = Employee.class;// ========== 2. 反射创建对象 ==========// 调用无参构造器实例化对象(要求 Employee 有无参构造)Object obj = clazz.newInstance();// ========== 3. 反射获取私有字段 ==========// getDeclaredField 可获取私有字段,需配合 setAccessible(true) 突破封装Field enoField = clazz.getDeclaredField("eno");Field nameField = clazz.getDeclaredField("realName");Field salaryField = clazz.getDeclaredField("salary");// ========== 4. 暴力反射:开启私有字段访问权限 ==========// 即使字段是 private,也能通过此方法赋值enoField.setAccessible(true);nameField.setAccessible(true);salaryField.setAccessible(true);// ========== 5. 反射赋值私有字段 ==========// 等价于:obj.eno = "T001"; enoField.set(obj, "T001");// 等价于:obj.realName = "水产张总";nameField.set(obj, "水产张总");// 等价于:obj.salary = 456.778;salaryField.setDouble(obj, 456.778);// ========== 6. 验证结果 ==========// 调用 Employee 的 toString() 输出对象内容System.out.println(obj);}
}// 普通 Java 类,包含私有字段和 toString 方法
class Employee {// 私有字段:体现封装性private String eno;private String realName;private String phoneNumber;private int level;private double salary;// 重写 toString,自定义对象打印格式@Overridepublic String toString() {return "Employee{" +"eno='" + eno + '\'' +", realName='" + realName + '\'' +", phoneNumber='" + phoneNumber + '\'' +", level=" + level +", salary=" + salary +'}';}
}

取值:

public class Test9 {public static void main(String[] args) throws IllegalAccessException {// 1. 创建 Employee 对象(通过构造器传参初始化)Employee emp = new Employee("T002", "孙乐", "1310988442", 8, 4567.8);// 2. 调用 info 方法,反射打印对象字段信息info(emp);}public static void info(Object obj) throws IllegalAccessException {// 3. 获取对象的 Class 对象(反射入口)Class clazz = obj.getClass();// 4. 获取类的所有**声明的字段**(包括 private)Field[] fields = clazz.getDeclaredFields();// 5. 遍历字段,逐个处理for (Field f : fields) {// 6. 暴力反射:突破 private 限制(允许访问私有字段)f.setAccessible(true);// 7. 获取字段的类型(判断是 int、double 还是其他类型)Class fieldType = f.getType();// 8. 根据字段类型,调用不同的 get 方法if (fieldType == int.class) {// int 类型:用 getInt 获取值System.out.printf("%s = %s%n", f.getName(), f.getInt(obj));} else if (fieldType == double.class) {// double 类型:用 getDouble 获取值System.out.printf("%s = %s%n", f.getName(), f.getDouble(obj));} else {// 其他类型(如 String):用 get 获取值System.out.printf("%s = %s%n", f.getName(), f.get(obj));}}}
}// 员工类:包含私有字段和构造器
class Employee {// 私有字段(体现封装性)private String eno;private String realName;private String phoneNumber;private int level;private double salary;// 无参构造(未使用,但保留)public Employee() {}// 全参构造:用于初始化对象public Employee(String eno, String realName, String phoneNumber, int level, double salary) {this.eno = eno;this.realName = realName;this.phoneNumber = phoneNumber;this.level = level;this.salary = salary;}// 重写 toString:自定义对象打印格式(main 中未直接调用,但可用于调试)@Overridepublic String toString() {return "Employee{" +"eno='" + eno + '\'' +", realName='" + realName + '\'' +", phoneNumber='" + phoneNumber + '\'' +", level=" + level +", salary=" + salary +'}';}
}

7.反射获取成员方法

在Java中反射包中,每一个成员方法用Method对象来表示,通过Class类提供的方法可以获取类中的成员方法对象。

在这里插入图片描述

eg:

import java.lang.reflect.Method;// Class 类型:用来封装某一个class类的类型信息(类名、构造方法、成员变量[字段]、实例方法)
// Constructor类型:用来封装一个构造方法
// Field类型:用来封装一个成员变量[字段]
// Method类型:用于封装一个方法
public class Test10 {public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {// 硬编码// String s = new String("just do IT");// String result = s.substring(0,4);// System.out.println(result);//1、反射第一步:先获取到Class对象Class clazz = String.class;// 创建实例对象Constructor constructor = clazz.getConstructor(String.class);Object s = constructor.newInstance("just do IT");// 根据方法名称,获取对应的Method对象Method method = clazz.getDeclaredMethod("substring", int.class, int.class);// invoke()执行方法// 硬编码 String result = s.substring(0,4);Object returnValue = method.invoke(s, 0, 4);System.out.println("返回值:" + returnValue);// 获取String类的所有定义方法// Method[] methods = clazz.getDeclaredMethods();// for (Method method : methods){//     System.out.println(method);// }}
}

eg:静态方法的调用,传对象为null

import java.lang.reflect.Method;// 静态方法的调用
public class Test11 {public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {// ========== 硬编码方式(被注释示例) ==========// 直接调用 Math.log10(567),并输出结果+1// int result = (int) Math.log10(567);// System.out.println(result + 1);// ========== 反射方式调用静态方法 ==========// 1. 获取 Math 类的 Class 对象Class clazz = Math.class;// 2. 获取静态方法 log10:参数类型是 doubleMethod method = clazz.getDeclaredMethod("log10", double.class);// 3. 调用静态方法:因静态方法属于类,而非对象,所以 invoke 的第一个参数传 nullObject returnValue = method.invoke(null, 567.0);// 4. 输出反射调用结果System.out.println(returnValue);}
}

8.综合例子

package 第二周.day3;import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Scanner;public class Test13 {public static void main(String[] args) {Scanner input = new Scanner(System.in);try {while (true) {System.out.print("请输入目标工具类名:");String className = input.nextLine(); // 第二周.day3.CommandSystem.out.print("请输入目标方法名称:");String methodName = input.nextLine(); // growif ("exit".equals(className) && "null".equals(methodName)) {System.out.println("程序退出了");break;}// 判断方法是否有参数,并执行该方法Class classzz = Class.forName(className);Method[] declaredMethods = classzz.getDeclaredMethods();Method targetmethod = null;for (Method method : declaredMethods) {if (methodName.equals(method.getName())) {targetmethod = method;break;}}if (targetmethod == null) {System.out.println("目标方法" + methodName + "不存在");continue;}Object[] objs = new Object[targetmethod.getParameterCount()];//遍历的当前方法有几个参数,就设置几次容量,传几次参数for (int i = 1; i <= targetmethod.getParameterCount(); i++) {System.out.println("请输入第:" + i + "个参数");objs[i - 1] = input.nextInt();}//创建实例Constructor constructor = classzz.getConstructor();Object o = constructor.newInstance();targetmethod.invoke(o, objs);}} catch (ClassNotFoundException | NoSuchMethodException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} finally {input.close();}}
}class Command {public Command() {}public void clear() {System.out.println("执行清空操作!");}public void init(int initSize, int initLocation) {System.out.println("执行初始化操作!");System.out.println("初始化长度 = " + initSize);System.out.println("初始化位置 = " + initLocation);}public void grow(int size) {System.out.println("执行扩容操作!");System.out.println("扩容量 = " + size);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/95451.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/95451.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/95451.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Grafana Tempo日志跟踪平台

以下是Grafana Tempo文档的总结&#xff08;基于最新版文档内容&#xff09;&#xff1a; 核心概念 分布式追踪系统&#xff1a;Tempo是开源的分布式追踪后端&#xff0c;专注于高吞吐量、低成本存储和与现有监控生态的深度集成 架构组成&#xff1a; Distributor&#xff1a…

Qt基本控件

Qt 的基本控件是构建用户界面的基础&#xff0c;涵盖了按钮、输入框、容器、显示组件等&#xff0c;适用于传统 Widget 开发&#xff08;基于 QWidget&#xff09;。以下是常用基本控件的分类总结&#xff1a;一、按钮类控件用于触发交互操作&#xff0c;如提交、取消、选择等。…

用Voe3做AI流量视频,条条10W+(附提示词+白嫖方法)

最近 AI 视频的风从大洋彼岸吹过来&#xff0c;Voe3 的技术升级&#xff0c;诞生了很多很有意思的玩法。 比如&#xff1a;AI ASMR 切水果解压视频&#xff0c;卡皮巴拉旅行博主、雪怪 AI Vlog&#xff0c;动物奥运会、第一人称视角穿越古战场直播。 这些视频的流量很好&…

嵌入式学习的第四十八天-中断+OCP原则

一、GIC通用中断控制器 1.GIC通用中断控制器 GIC 是 ARM 公司给 Cortex-A/R 内核提供的一个中断控制器&#xff0c;GIC接收众多外部中断&#xff0c;然后对其进行处理&#xff0c;最终通过VFIQ、VIRQ、FIQ 和 IRQ给内核&#xff1b;这四个 信号的含义如下&#xff1a; VFIQ:虚拟…

一周学会Matplotlib3 Python 数据可视化-绘制条形图(Bar)

锋哥原创的Matplotlib3 Python数据可视化视频教程&#xff1a; 2026版 Matplotlib3 Python 数据可视化 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili 课程介绍 本课程讲解利用python进行数据可视化 科研绘图-Matplotlib&#xff0c;学习Matplotlib图形参数基本设置&…

阿里研发效能提升【60篇】

阿里研发效能提升【60篇】 1、建立研发效能提升的系统框架 01、《从DevOps到BizDevOps&#xff0c;研发效能提升的系统方法》 视频版&#xff1a;2021云栖大会云效BizDevOps论坛 文字版&#xff1a;深度 | 从DevOps到BizDevOps, 研发效能提升的系统方法-阿里云开发者社区 …

面试实战 问题二十六 JDK 1.8 核心新特性详解

JDK 1.8 核心新特性详解 1. Lambda表达式 最核心的特性&#xff0c;简化函数式编程&#xff0c;语法&#xff1a;(参数) -> 表达式 // 传统方式 Runnable r1 new Runnable() {Overridepublic void run() {System.out.println("传统方式");} };// Lambda方式 Runn…

STM32H743开发周记问题汇总(串口通讯集中)

溢出错误出现的串口接收过程中&#xff0c;中断接收在溢出后无法进入&#xff0c;需要重点考虑溢出问题&#xff0c;以下是溢出恢复代码波特率115200 优先级0-1 高于定时器 初步诊断是数据流导致的接收溢出问题/*** brief 检查并清除UART溢出错误&#xff08;带状态…

Linux中FTP配置与vsftpd服务部署指南

Linux中FTP配置与vsftpd服务部署指南 一、FTP 核心概念 1、基本定义 文件传输协议&#xff08;FTP&#xff09;&#xff0c;基于 C/S模式 工作。控制端口&#xff1a;21&#xff08;身份验证与指令传输&#xff09; 数据端口&#xff1a;20&#xff08;主动模式数据传输&#x…

Web UI自动化测试的早期介入?

在传统研发流程中&#xff0c;Web UI自动化测试常被视为“后期活动”——必须等待前端界面完全稳定才能启动。这种滞后导致自动化测试难以覆盖早期迭代&#xff0c;形成“开发等测试、测试等稳定”的恶性循环。本文将系统破解这一困局&#xff0c;提供一套从需求阶段介入、持续…

基于学科竞赛的高职计算机网络教学解决方案

一、引言《关于深化产教融合的若干意见》明确提出 “推行面向企业真实生产环境的任务培养模式”&#xff0c;为我国职业教育发展指明了产教深度融合的方向。在数字经济时代&#xff0c;计算机网络技术正以前所未有的速度迭代更新&#xff0c;产业界对具备前沿技术应用能力和实践…

猿大师中间件:Chrome网页内嵌PhotoShop微信桌面应用程序

随着桌面应用程序集成到网页的需求不断增长&#xff0c;尤其在Chrome浏览器缺乏原生调用EXE功能的情况下&#xff0c;传统网页内嵌解决方案面临失效挑战&#xff0c;猿大师中间件因此发展成为当前主流方案。 2025年猿大师发布了EXE、OCX、COM三个通用组件&#xff0c;自此猿大…

EF (Entity Framework) vs LINQ to SQL vs SqlSugar 全方位对比分析

文章目录1. 概述与背景介绍1.1 Entity Framework (EF)1.2 LINQ to SQL1.3 SqlSugar2. 架构设计对比2.1 EF架构设计2.2 LINQ to SQL架构2.3 SqlSugar架构3. 性能对比3.1 基准测试数据3.2 性能分析3.3 内存使用4. 功能特性对比4.1 数据库支持4.2 主要功能对比4.3 高级特性5. 开发…

MySQL 多表联查与内外连接详解

多表联查是关系型数据库的核心操作&#xff0c;用于从多个表中关联数据。MySQL 支持多种连接方式&#xff0c;最常用的是内连接和外连接&#xff08;左/右/全外连接&#xff09;。一、多表联查基础语法 SELECT 列列表 FROM 表1 [连接类型] JOIN 表2 ON 连接条件 [连接类型] JOI…

《网络爬虫》

网络爬虫&#xff0c;是一种自动化程序&#xff0c;用于抓取互联网上的数据。它们通过模拟浏览器行为&#xff0c;抓取网页内容并提取有用信息。爬虫广泛应用于数据采集、搜索引擎索引、竞争对手分析等领域。爬虫的工作流程&#xff1a;请求目标网页&#xff1a;爬虫首先发送 H…

openpnp - 顶部相机环形灯光DIY

文章目录openpnp - 顶部相机环形灯光DIY概述笔记ENDopenpnp - 顶部相机环形灯光DIY 概述 底部相机灯光用环形灯(用钣金折弯成一个10mm高的矩形盒子)是可以的。因为吸嘴落到Z方向和PCB平齐时&#xff0c;用COB灯带装在一个矩形盒子中正好能照射到吸嘴尖端高度附近。 顶部相机…

[AI React Web] E2B沙箱 | WebGPU | 组件树 | 智能重构 | 架构异味检测

第三章&#xff1a;E2B沙箱交互 在前两章中&#xff0c;我们掌握了对话状态管理和AI代码生成管道的运作原理。 但生成代码如何真正运行&#xff1f;这正是E2B沙箱交互的核心价值。 架构定位 E2B沙箱是专为open-lovable打造的虚拟计算环境&#xff0c;具备以下核心能力&…

Redis宝典

Redis是什么 Redis是开源的&#xff0c;使用C语言编写的&#xff0c;支持网络交互&#xff0c;可基于内存也可持久化到本地磁盘的Key-Value数据库。 优点&#xff1a; 因为Redis是基于内存的&#xff0c;所以数据的读取速度很快Redis支持多种数据结构&#xff0c;包括字符串Str…

MyBatis-Plus 分页失效问题解析:@Param 注解的影响与解决方案

引言在 Spring Boot MyBatis-Plus 的开发中&#xff0c;分页查询是常见的需求。然而&#xff0c;有时我们会遇到分页失效的问题&#xff0c;尤其是在方法参数上添加 Param 注解后。本文将通过一个实际案例&#xff0c;分析 Param 注解如何影响 MyBatis-Plus 的分页机制&#x…

机器学习——模型的简单优化

在训练模型时我们可能会遇到模型不满足于预期需要进行改善的环节&#xff0c;这些情况通常包括以下几种常见问题和对应的解决方案&#xff1a;数据质量不足数据量过少&#xff1a;当训练样本不足时&#xff0c;模型难以学习到有效的特征表示。建议通过数据增强&#xff08;如图…