当前位置: 首页 > news >正文

Java --- 反射

目录

一.什么是反射?

二.反射的核心方法和功能: 

1.获取类的元信息:

2. 动态实例化对象:

3. 访问字段(包括私有字段):

4. 调用方法(包括私有方法):

5.动态代理:


一.什么是反射?

Java 反射(Reflection)是 Java 提供的一种功能,可以在运行时检查类、接口、字段和方法的信息,同时还可以动态调用对象的方法或构造器,甚至修改字段的值。反射使程序具有很强的动态性,但也可能带来一定的性能和安全问题。

反射的核心是 java.lang.reflect 包,其中包含了如下主要类:

  • Class:提供了类的元信息。
  • Field:表示类的字段。
  • Method:表示类的方法。
  • Constructor:表示类的构造方法。

class(包括interface)的本质是数据类型(Type)。无继承关系的数据类型无法赋值:

Number n = new Double(123.456); // OK
String s = new Double(123.456); // compile error!

class是由JVM在执行过程中动态加载的。JVM在第一次读取到一种class类型时,将其加载进内存。每加载一种class,JVM就为其创建一个Class类型的实例,并关联起来。它长这样:

public final class Class {private Class() {}
}

所以,JVM持有的每个Class实例都指向一个数据类型(classinterface),并且一个Class实例包含了该class的所有完整信息。

由于JVM为每个加载的class创建了对应的Class实例,并在实例中保存了该class的所有信息,包括类名、包名、父类、实现的接口、所有方法、字段等。因此,如果获取了某个Class实例,我们就可以通过这个Class实例获取到该实例对应的class的所有信息。而通过Class实例获取class信息的方法称为反射(Reflection)

二.反射的核心方法和功能: 

反射的核心方法和功能如下:

  1. 获取类的元信息
  2. 动态实例化对象
  3. 访问字段(包括私有字段)
  4. 调用方法(包括私有方法)

1.获取类的元信息:

通过反射获取类的包名、类名和方法等信息。

import java.lang.reflect.Method;public class ReflectionExample {public static void main(String[] args) {try {// 获取 Class 对象:// 1. 使用 Class.forName()Class<?> clazz = Class.forName("java.util.ArrayList");// 2. 使用 类名.classClass<?> clazz2 = ArrayList.class;// 3. 使用对象.getClass()ArrayList<String> list = new ArrayList<>();Class<?> clazz3 = list.getClass();System.out.println(clazz1 == clazz2); // trueSystem.out.println(clazz2 == clazz3); // true// 打印类名和包名System.out.println("类名: " + clazz.getName());System.out.println("简单类名: " + clazz.getSimpleName());System.out.println("包名: " + clazz.getPackage().getName());// 获取所有方法Method[] methods = clazz.getMethods();System.out.println("类中的方法:");for (Method method : methods) {System.out.println(method.getName());}} catch (ClassNotFoundException e) {e.printStackTrace();}}
}
输出示例:
类名: java.util.ArrayList
简单类名: ArrayList
包名: java.util
类中的方法:
add
remove
size
clear
...
  • Class.forName:通过类的完全限定名动态加载类。
  • getMethods:返回类及其父类的所有公共方法。

注意一下Class实例比较和instanceof的差别:

Integer n = new Integer(123);boolean b1 = n instanceof Integer; // true,因为n是Integer类型
boolean b2 = n instanceof Number; // true,因为n是Number类型的子类boolean b3 = n.getClass() == Integer.class; // true,因为n.getClass()返回Integer.class
Class c1 = n.getClass();
Class c2 = Number.class;
boolean b4 = c1 == c2; // false,因为Integer.class != Number.class

instanceof不但匹配指定类型,还匹配指定类型的子类。而==判断class实例可以精确地判断数据类型,但不能作子类型比较

而通常情况下,我们应该用instanceof判断数据类型,因为在面向抽象编程的时候,我们不关心具体的子类型。只有在需要精确判断一个类型是不是某个class的时候,我们才使用==判断class实例。

注意:数组(例如String[])也是一种类,而且不同于String.class,它的类名是[Ljava.lang.String;。此外,JVM为每一种基本类型如int也创建了Class实例,通过int.class访问。 

因为反射的目的是为了获得某个实例的信息。因此,当我们拿到某个Object实例时,我们就可以通过反射获取该Objectclass信息:

void printObjectInfo(Object obj) {Class clazz = obj.getClass();
}

2. 动态实例化对象:

通过反射动态创建类的实例。

假如我们获取到了一个Class实例,我们就可以通过该Class实例来创建对应类型的实例: 

// 获取String的Class实例:
Class cls = String.class;
// 创建一个String实例:
String s = (String) cls.newInstance();

上述代码相当于new String()。通过Class.newInstance()可以创建类实例,它的局限是:只能调用public的无参数构造方法。带参数的构造方法,或者非public的构造方法都无法通过Class.newInstance()被调用。

为了调用任意的构造方法,Java的反射API提供了Constructor对象,它包含一个构造方法的所有信息,可以创建一个实例。Constructor对象和Method非常类似,不同之处仅在于它是一个构造方法,并且调用结果总是返回实例: 

import java.lang.reflect.Constructor;public class DynamicInstanceExample {public static void main(String[] args) {try {// 获取 Class 对象Class<?> clazz = Class.forName("java.lang.String");// 获取构造方法(使用 getConstructor 获取特定参数的构造器)Constructor<?> constructor = clazz.getConstructor(String.class);// 创建对象实例(通过 newInstance 动态创建对象)Object instance = constructor.newInstance("Hello Reflection");System.out.println("实例内容: " + instance); // 实例内容: Hello Reflection// 获取构造方法Integer(int):Constructor cons1 = Integer.class.getConstructor(int.class);// 调用构造方法:Integer n1 = (Integer) cons1.newInstance(123);System.out.println(n1); // 123// 获取构造方法Integer(String)Constructor cons2 = Integer.class.getConstructor(String.class);Integer n2 = (Integer) cons2.newInstance("456");System.out.println(n2); // 456} catch (Exception e) {e.printStackTrace();}}
}

3. 访问字段(包括私有字段):

对任意的一个Object实例,只要我们获取了它的Class,就可以获取它的一切信息。而在Java中,Field类是Java反射机制的一部分,用于表示类的成员变量。通过Field对象,我们可以获取类的字段(成员变量)的信息,并且能够在运行时动态地访问或修改这些字段的值。

要获取类的字段(成员变量),需要通过Class对象获取对应的Field对象。可以通过以下两种方式:

  1. 获取类的所有字段:使用 getDeclaredFields()方法可以获取类中所有的字段,包括私有字段(private)和公共字段(public)。

  2. 获取某个特定字段:使用 getDeclaredField(String name)方法获取指定名称的字段。

  • Field getField(name):根据字段名获取某个public的field(包括父类)
  • Field getDeclaredField(name):根据字段名获取当前类的某个field(不包括父类)
  • Field[] getFields():获取所有public的field(包括父类)
  • Field[] getDeclaredFields():获取当前类的所有field(不包括父类) 
import java.lang.reflect.Field;class Person {private String name = "John";
}public class AccessPrivateFieldExample {public static void main(String[] args) {try {Person person = new Person();Class<?> clazz = person.getClass();// 获取类的私有字段Field field = clazz.getDeclaredField("name");field.setAccessible(true); // 取消 Java 的访问权限检查// 获取和修改字段值System.out.println("原始值: " + field.get(person));field.set(person, "Alice");System.out.println("修改后的值: " + field.get(person));} catch (Exception e) {e.printStackTrace();}}
}

 下面是使用field对不同权限属性的访问:

// reflection
public class Main {public static void main(String[] args) throws Exception {Class<?> stdClass = Student.class;// 获取public字段"score":System.out.println(stdClass.getField("score"));// 获取继承的public字段"name":System.out.println(stdClass.getField("name"));// 获取private字段"grade":System.out.println(stdClass.getDeclaredField("grade"));}
}class Student extends Person {public int score;private int grade;
}class Person {public String name;
}

还有其他的常见方法:

  • getName():获取字段的名称。
  • getType():获取字段的类型(返回Class对象)。
  • getModifiers():获取字段的修饰符(如publicprivate等)。
  • set(Object obj, Object value):设置字段值。
  • get(Object obj):获取字段值。

Field类使得Java反射具有非常强的动态性,允许我们在程序运行时进行更细粒度的操作。不过,过多使用反射可能会影响性能,并增加代码的复杂性,因此建议在需要动态行为或框架开发时使用。

4. 调用方法(包括私有方法):

我们已经能通过Class实例获取所有Field对象,同样我们也可以通过Class实例获取所有Method信息。 

Class类提供了以下几个方法来获取Method

  • Method getMethod(name, Class...):获取某个publicMethod(包括父类)
  • Method getDeclaredMethod(name, Class...):获取当前类的某个Method(不包括父类)
  • Method[] getMethods():获取所有publicMethod(包括父类)
  • Method[] getDeclaredMethods():获取当前类的所有Method(不包括父类)
// reflection
public class Main {public static void main(String[] args) throws Exception {Class stdClass = Student.class;// 获取public方法getScore,参数为String:System.out.println(stdClass.getMethod("getScore", String.class));// 获取继承的public方法getName,无参数:System.out.println(stdClass.getMethod("getName"));// 获取private方法getGrade,参数为int:System.out.println(stdClass.getDeclaredMethod("getGrade", int.class));}
}class Student extends Person {public int getScore(String type) {return 99;}private int getGrade(int year) {return 1;}
}class Person {public String getName() {return "Person";}
}

一个Method对象包含一个方法的所有信息:

  • getName():返回方法名称,例如:"getScore"
  • getReturnType():返回方法返回值类型,也是一个Class实例,例如:String.class
  • getParameterTypes():返回方法的参数类型,是一个Class数组,例如:{String.class, int.class}
  • getModifiers():返回方法的修饰符,它是一个int,不同的bit表示不同的含义。

我们正常的(直接的)方法调用指的是通过对象直接调用类中的方法。例如:

String s = "Hello world";
String result = s.substring(6);  // 直接调用substring方法
System.out.println(result);  // 输出 "world"

反射调用则是通过Java反射机制来动态地调用对象的方法。通过Method.invoke(),可以在运行时决定调用哪个方法,并传递参数。例如:

import java.lang.reflect.Method;public class Main {public static void main(String[] args) throws Exception {String s = "Hello world";Method m = String.class.getMethod("substring", int.class);  // 获取substring方法String result = (String) m.invoke(s, 6);  // 动态调用substring方法System.out.println(result);  // 输出 "world"}
}

invoke的第一个参数是对象实例,即在哪个实例上调用该方法,后面的可变参数要与方法参数一致,否则将报错。 

反射调用特点:

  • 使用invoke时,方法的调用是动态的,在运行时解析方法。你需要提供Method对象来引用类中的方法。
  • 可以调用私有方法或无法直接访问的非公共方法(通过setAccessible(true)来访问)。
  • 反射调用的参数和返回值是通过Object类型来传递和返回的,因此需要进行类型转换。
  • 反射方法的调用通常比直接调用慢,因为它需要通过反射机制来查找和执行方法。
  • 能动态地加载和调用方法,使得代码更具灵活性(例如插件系统、动态执行等)。

invoke方法比正常的直接方法调用灵活,但代价是性能上有所牺牲,并且不能享受编译时的类型检查。

特性正常方法调用反射调用 invoke
性能较高,直接编译时检查方法较低,涉及反射和运行时解析
编译时检查直接通过类的方法签名进行检查不在编译时检查,运行时才解析
灵活性方法在编译时已固定,不能动态选择方法可以动态选择方法,适用于动态行为
方法调用直接调用方法,参数明确需要通过反射获取Method对象,并传递参数
访问控制只能访问公共方法可以通过setAccessible(true)访问私有方法

eg: 

import java.lang.reflect.Method;class Calculator {private int add(int a, int b) {return a + b;}
}public class InvokePrivateMethodExample {public static void main(String[] args) {try {Calculator calculator = new Calculator();Class<?> clazz = calculator.getClass();// 获取私有方法Method method = clazz.getDeclaredMethod("add", int.class, int.class);method.setAccessible(true);// 调用私有方法Object result = method.invoke(calculator, 10, 20);System.out.println("结果: " + result);} catch (Exception e) {e.printStackTrace();}}
}

5.动态代理:

Java的动态代理(Dynamic Proxy)是指在程序运行时,动态生成代理类并创建代理对象的技术。通过动态代理,可以在不修改目标类的情况下,增加额外的功能或逻辑(如日志记录、性能监控、权限控制等)。Java的动态代理有两种常见的实现方式:JDK动态代理CGLIB动态代理。在这里,下面我们将重点讲解JDK动态代理,并涉及CGLIB的相关内容。

(1)动态代理的思想:

通过反射机制,在运行时创建一个代理类,该类实现目标接口,并且代理类内部将调用实际目标对象的方法。在调用过程中,代理类可以执行额外的操作(如日志、事务等)再调用目标方法。

(2)动态代理的好处:

  • 无需修改目标类:代理类不需要继承或实现目标类,只需要实现目标类的接口。
  • 灵活性高:代理行为可以在运行时动态生成和调整。
  • 增强功能:可以在不改变原有代码的情况下为目标方法提供额外的功能。

那么如何不编写实现类,直接在运行期创建某个interface的实例呢?

动态代理(Dynamic Proxy)的机制:可以在运行期动态创建某个interface的实例。

我们仍然先定义了接口Hello,但是我们并不去编写实现类,而是直接通过JDK提供的一个Proxy.newProxyInstance()创建了一个Hello接口对象。这种没有实现类但是在运行期动态创建了一个接口对象的方式,我们称为动态代码。JDK提供的动态创建接口对象的方式,就叫动态代理。

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;public class Main {public static void main(String[] args) {// InvocationHandler 是一个接口,它必须实现 invoke() 方法。这个方法在代理实例的方法被调用时执行。InvocationHandler handler = new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println(method);if (method.getName().equals("morning")) {System.out.println("Good morning, " + args[0]);}return null;}};// 创建了一个Hello接口对象。这种没有实现类但是在运行期动态创建了一个接口对象的方式,我们称为动态代码Hello hello = (Hello) Proxy.newProxyInstance(Hello.class.getClassLoader(), // 传入用于加载代理类的ClassLoader,通常可以使用接口的getClassLoader()来获取。new Class[] { Hello.class }, // 传入需要实现的接口数组handler // 传入处理调用方法的InvocationHandler,包含具体的业务逻辑); // 调用代理对象hello的morning方法hello.morning("Bob");}
}interface Hello {void morning(String name);
}

invoke() 方法接收三个参数:

  • proxy: 被代理的对象(即代理类实例)。
  • method: 被调用的方法对象,包含了方法的名称、参数类型等信息。
  • args: 被调用方法的参数。

 

相关文章:

Java --- 反射

目录 一.什么是反射&#xff1f; 二.反射的核心方法和功能&#xff1a; 1.获取类的元信息&#xff1a; 2. 动态实例化对象&#xff1a; 3. 访问字段&#xff08;包括私有字段&#xff09;&#xff1a; 4. 调用方法&#xff08;包括私有方法&#xff09;&#xff1a; 5.…...

python编程Day12-属性和方法的分类

私有和公有 在python中 定义类的时候&#xff0c;可以给 属性和方法设置 访问权限&#xff0c;即规定在什么地方可以使用。 权限一般分为两种&#xff1a;公有权限、私有权限 公有权限 定义&#xff1a;直接定义的属性和方法就是公有的特点&#xff1a; 可以在任何地方访问和使…...

C#实现TCP客户端和服务器

本文将介绍如何使用C#实现TCP客户端和服务器的基本功能&#xff0c;客户端与服务器可以相互发送消息。 效果展示 服务器端实现 首先&#xff0c;我们实现TCP服务器。以下是服务器端所需的类和代码&#xff1a; using System; using System.Collections.Generic; using Syste…...

数据库编程: JDBC 中数据库驱动包的安装,配置及引用

目录 驱动包的下载安装 1. 去oracle 官方网站下载 2. github 的开源软件 3. 中央仓库(推荐使用这个) 驱动包的配置及引用 1. 第一步: 打开idea, 在 idea 中创建新的项目 2. 然后我们要在 jdbc_1 目录下创建一个新的目录包 3. 最后引入MySQL 的驱动包, 作为项目的依赖 尾…...

mx linux 在konsole终端中无法输入中文的解决方法

在mx linux系统中&#xff0c;浏览器可以正常输入中文&#xff0c;但是终端窗口中无法输入中文的解决方法&#xff0c;可以通过以下步骤安装 fcitx - frontend - qt5 组件&#xff1a; 1. 打开终端。你可以通过系统菜单或者快捷键&#xff08;如 Ctrl Alt T &#xff09;来…...

./configure 安装ngnix的命令

./configure 是一个在 Unix 和类 Unix 系统中常用的 shell 脚本命令&#xff0c;主要用于配置软件源代码包&#xff0c;以便进行编译和安装。这个命令通常在从源代码编译软件之前执行&#xff0c;它会自动检测系统的配置并生成适合该系统的 Makefile。 以下是 ./configure 脚本…...

网络安全之接入控制

网络安全之接入控制 身份鉴别 ​ 定义:验证主题真实身份与其所声称的身份是否符合的过程&#xff0c;主体可以是用户、进程、主机。同时也可实现防重放&#xff0c;防假冒。 ​ 分类:单向鉴别、双向鉴别、三向鉴别。 ​ 主题身份标识信息:密钥、用户名和口令、证书和私钥 I…...

2.1 关系模型

关系模型的基本概念 关系&#xff1a;二维表&#xff0c;通常在数据库中表现为一个表&#xff1b; 属性&#xff1a;关系中的一个列即为关系的一个属性&#xff1b; 域&#xff1a; 每个属性的取值范围即为该属性的域&#xff1b; 元组&#xff1a;关系中的一个行是一个元组…...

深入浅出 Go 语言 sync包中的互斥锁、条件变量

深入浅出 Go 语言 sync包中的互斥锁、条件变量 引言 在并发编程中&#xff0c;多个 Goroutine 同时访问共享资源可能会导致数据竞争&#xff08;Race Condition&#xff09;&#xff0c;进而引发程序的不一致性或崩溃。为了确保并发程序的正确性和稳定性&#xff0c;Go 语言提…...

利用Python实现子域名简单收集

免责申明 本文仅是用于学习研究子域名信息收集&#xff0c;请勿用在非法途径上&#xff0c;若将其用于非法目的&#xff0c;所造成的一切后果由您自行承担&#xff0c;产生的一切风险和后果与笔者无关&#xff1b;本文开始前请认真详细学习《‌中华人民共和国网络安全法》【学法…...

npm发布插件到私有仓库保姆级教程

在开发项目的过程中&#xff0c;我们经常需要安装插件依赖&#xff0c;那么怎么把自己开发的组件封装成一个插件&#xff0c;并发布到npm 插件市场或者上传到私有仓库里面呢&#xff1f;今天总结下自己发布插件到私有仓库的记录&#xff1a; 一、创建组件 执行命令创建一个空…...

利用Java easyExcel库实现高效Excel数据处理

在Java应用程序中&#xff0c;处理Excel文件是一项常见任务&#xff0c;尤其是在需要读取、写入或分析大量数据时。easyExcel是一个基于Java的高性能Excel处理库&#xff0c;它提供了简洁的API和优化的性能&#xff0c;以简化Excel文件的处理。本文将指导您如何使用easyExcel库…...

基于Springboot的校园交友网站设计与实现

1.1 管理信息系统概述 管理信息系统是计算机在信息管理领域的一种实用技术。通过运用管理科学、数学和计算机应用的原理及方法&#xff0c;在符合软件工程规范的原则下&#xff0c;形成一套完整的理论和方法体系。是一个以人、计算机和其他外部设备组成的可以进行信息的收集、…...

android studio 读写文件操作(应用场景三)

android studio版本&#xff1a;2023.3.1 patch2 例程&#xff1a;filesaveandread 其实我写这个都是我记录我要做后个数独小游戏&#xff0c;每一个都是为了解决一个问题。即是分享也是备忘&#xff0c;反正我什么都不会&#xff0c;就是一顿瞎改&#xff0c;不行就研究。这…...

小程序 —— Day1

组件 — view和scroll-view view 类似于HTML中的div&#xff0c;是一个块级元素 案例&#xff1a;通过view组件实现页面的基础布局 scroll-view 可滚动的视图区域&#xff0c;用来实现滚动列表效果 案例&#xff1a;实现纵向滚动效果 scroll-x属性&#xff1a;允许横向滚动…...

使用 PyTorch 和 Horovod 来编写一个简单的分布式训练 demo

使用 PyTorch 和 Horovod 来编写一个简单的分布式训练 demo&#xff0c;可以帮助你理解如何在多GPU或多节点环境中高效地训练深度学习模型。Horovod 是 Uber 开发的一个用于分布式训练的框架&#xff0c;它支持 TensorFlow、Keras、PyTorch 等多个机器学习库。下面是一个基于 P…...

【Linux】以 CentOS 为例备份与恢复/home分区,并调整分区容量

在 Linux 系统中&#xff0c;这里举例对 /home 目录进行备份、重建和恢复操作&#xff0c;并调整分区大小、更换文件系统或修复损坏的分区等。 〇、前提条件 确认文件系统类型为 xfs。 确认 /home 目录确实没有重要数据&#xff0c;或者已经做好了数据备份。 确保在执行这些…...

OpenAI 12Days 第二天 强化微调(RFT):推动语言模型在科学研究中的应用

OpenAI 12Days 第二天 强化微调&#xff08;RFT&#xff09;&#xff1a;推动语言模型在科学研究中的应用 文章目录 OpenAI 12Days 第二天 强化微调&#xff08;RFT&#xff09;&#xff1a;推动语言模型在科学研究中的应用RFT的工作原理与应用领域案例研究&#xff1a;基因突变…...

神经网络的梯度反向传播计算过程,举例说明

目录 神经网络的梯度反向传播计算过程 网络结构 权重和偏置 激活函数 前向传播 损失函数 反向传播 参数更新 举例 神经网络的梯度反向传播计算过程 为了说明神经网络的梯度反向传播计算过程,我们考虑一个简单的全连接网络,该网络有一个输入层、一个隐藏层和一个输出…...

定点数乘法:补码一位算法(booth算法)

方法 初始化 将被乘数A放在寄存器A中。 将乘数B放在寄存器B中&#xff0c;并在最低位添加一个额外的位Q(-1) 0。 结果寄存器P初始化为0&#xff0c;长度为2n位。 迭代过程&#xff08;重复n次&#xff09; 对于i从0到n-1&#xff1a; 检查乘数B的最后两位&#xff08;B 和…...

robots.txt

robots.txt 文件是网站管理者用来告知搜索引擎爬虫&#xff08;也称为机器人或蜘蛛&#xff09;哪些页面可以抓取&#xff0c;哪些页面不应该被抓取的一种文本文件。它位于网站的根目录下&#xff0c;并且文件名必须全部小写。这个文件对于SEO&#xff08;搜索引擎优化&#xf…...

如何用 JavaScript 操作 DOM 元素?

如何用 JavaScript 操作 DOM 元素&#xff1f;——结合实际项目代码示例讲解 在前端开发中&#xff0c;DOM&#xff08;文档对象模型&#xff09;操作是与页面交互的核心。通过 DOM 操作&#xff0c;开发者可以动态地修改页面内容、响应用户交互、控制样式等。JavaScript 提供…...

vue3使用后端传递的文件流进行文件预览

文章目录 一、 注意事项1、responseType设置为&#xff1a;arraybuffer2、Blob设置type&#xff0c;来源于后台封装的response.headers[content-type]3、使用encodeURIComponent()&#xff0c;避免符号影响文件名 二、java接口 一、 注意事项 1、responseType设置为&#xff1…...

ubuntu20.04设置远程桌面

安装xrdp sudo apt install xrdp 2、 检查xrdp状态 sudo systemctl status xrdp3、&#xff08;若为Ubuntu 20&#xff09;添加xrdp至ssl-cert sudo adduser xrdp ssl-cert 4、重启服务 sudo systemctl restart xrdp最后可以远程了&#xff0c;注意一个账号只能一个登录...

在vue3里使用scss实现简单的换肤功能

实现的换肤功能&#xff1a;主题色切换、亮色模式和暗黑模式切换、背景图切换 主题色就是网站主色&#xff0c;可以配置到组件库上面&#xff1b;亮色模式又分为两种风格&#xff1a;纯白风格和背景图风格&#xff0c;不需要背景图的话可以删掉这部分逻辑和相关定义&#xff1b…...

flyway执行sql遇到变量执行报错解决

前两天在公司使用flyway工具执行sql时&#xff0c;开发写的sql里面有变量&#xff0c;于是这个flyway工具不识别这个变量直接报错&#xff0c;不接着往下执行了。报错信息如下&#xff1a; flyway工具执行sql报错 information: No value provided for placeholder: ${ep1} 于是…...

解谜类游戏《迷失岛2》等如何抽象出一套通用高效开发框架?

解谜类游戏以精妙的谜题设计和引人入胜的故事叙述为特点&#xff0c;考验着玩家的智慧与观察力。《迷失岛2》与《南瓜先生2九龙城寨》正是这一领域的佳作。游戏以独特的艺术风格和玩法设计吸引了大量玩家&#xff0c;而它们背后隐藏着一套强大的框架。 上海胖布丁游戏的技术总…...

Ant Design Vue v4版本如何解决1px没有被postcss-px2rem转成rem的问题

背景说明 如果你的 Ant Design Vue 项目有要做适配的需求&#xff0c;那首先要选择一种适配方案。笔者选择的是用 postcss-px2rem 进行适配。笔者在配置了 postcss-px2rem的相关配置后&#xff0c;发现 postcss-px2rem 没有对 Ant Design Vue 进行适配。在网上看了一些文章之后…...

【系统架构设计师论文】云上自动化运维及其应用

随着云计算技术的迅猛发展,企业对云资源的需求日益增长。为了应对这一挑战,云上自动化运维(CloudOps)应运而生,它结合了DevOps理念和技术,通过自动化工具和流程来提高云环境的管理效率和服务质量。本文将探讨云上自动化运维的主要衡量指标,并详细介绍一个实际项目中如何…...

河南地质灾害资质办理的政策

一、资质分类 资质等级&#xff1a; 甲级资质&#xff1a;由自然资源部审批管理&#xff0c;适用于承担大型地质灾害防治项目。 乙级资质&#xff1a;由省、自治区、直辖市自然资源主管部门审批管理&#xff0c;适用于承担中型地质灾害防治项目。 丙级资质&#xff1a;由省…...

单例模式--懒汉 饿汉模式

一.啥是单例模式? 先介绍一下设计模式&#xff1a; 设计模式好⽐象棋中的 "棋谱". 红⽅当头炮, ⿊⽅⻢来跳. 针对红⽅的⼀些⾛法, ⿊⽅应招的时候有⼀些固定的套路. 按照套路来⾛局势就不会吃亏. 软件开发中也有很多常⻅的 "问题场景". 针对这些问题…...

HDD 2025年技术趋势深度分析报告

随着数据量的指数级增长以及人工智能&#xff08;AI&#xff09;、物联网&#xff08;IoT&#xff09;、云计算和视频监控等领域的需求激增&#xff0c;硬盘驱动器&#xff08;HDD&#xff09;行业正面临着前所未有的挑战与机遇。本报告旨在深入剖析2025年HDD技术的发展方向&am…...

关于uni-app的uni.showModal和indexOf的使用

这里使用showModal时&#xff0c;这个里面的content需要使用到字符串的形式&#xff0c;不能用到number类型 uni.showModal({title: 提示,content: "hello",success: function (res) {if (res.confirm) {console.log(用户点击确定);} else if (res.cancel) {console…...

Spring Data Elasticsearch

简介说明 spring-data-elasticsearch是比较好用的一个elasticsearch客户端&#xff0c;本文介绍如何使用它来操作ES。本文使用spring-boot-starter-data-elasticsearch&#xff0c;它内部会引入spring-data-elasticsearch。 Spring Data ElasticSearch有下边这几种方法操作El…...

汇编语言简要记录-1

汇编语言与汇编指令 汇编语言的主题是汇编指令 汇编指令与机器指令的差别在于指令的表示方法上 1、汇编指令是机器机器指令便于记忆的书写格式 2、汇编指令是机器指令的助记符 ag&#xff1a;机器指令 1000100111011000操作&#xff1a;将寄存器BX的值送到AX中汇编指令 MOV …...

Java程序猿搬砖笔记(十七)

文章目录 MySQL触发器ElasticSearch按日期分组查询每天的文档数量MySQL中order by排序将null排在最前或者最后面swagger3.0默认访问路径swagger3.0模块化配置MySQL中要少用UNION&#xff0c;多用UNION ALLElasticSearch Bucket & Metric聚合分析及嵌套聚合Mysql case when做…...

代码设计:设计模式:观察者模式

文章目录 定义类结构应用总结 定义 实现响应式编程的代码设计&#xff0c;即触发事件或数据变化时&#xff0c;将数据从被观察者类通过观察器传递给观察者处理&#xff0c;即被观察者类间接调用观察者类的方法处理事件或数据 类结构 被观察者类、观察器类、观察者类 被观察…...

第32天:安全开发-JavaEE应用Servlet路由技术JDBCMybatis数据库生命周期

时间轴&#xff1a; 32天主要学习内容&#xff1a; 1、JavaEE-HTTP-Servlet技术 2、JavaEE-数据库-JDBC&Mybatis java技术使用历史&#xff08;2023 &#xff09;&#xff1a; JavaEE-HTTP-Servlet&路由&周期: java学习范围&#xff1a; 3、Java: 功能:数据…...

如何使用Apache HttpClient来执行GET、POST、PUT和DELETE请求

Apache HttpClient 是一个功能强大且灵活的库&#xff0c;用于在Java中处理HTTP请求。 它支持多种HTTP方法&#xff0c;包括GET、POST、PUT和DELETE等。 本教程将演示如何使用Apache HttpClient来执行GET、POST、PUT和DELETE请求。 Maven依赖 要使用Apache HttpClient&…...

Next.js 系统性教学:加载界面、重定向与路由分组

更多有关Next.js教程&#xff0c;请查阅&#xff1a; 【目录】Next.js 独立开发系列教程-CSDN博客 目录 1. 加载界面与流式渲染 1.1 加载界面 (loading.js) 1.2 流式渲染 2. 路由重定向 2.1 基于服务器的重定向 2.2 动态重定向 2.3 中间件中的重定向 3. 路由分组 3.1…...

哪款云手机适合多开?常用云手机功能对比

在全球化和数字化时代&#xff0c;云手机以其独特的灵活性和高效性&#xff0c;成为多账号运营和数字营销的热门工具。云手机能够解决传统设备管理的诸多痛点&#xff0c;例如账号关联、硬件成本高等问题。本文将为您推荐多款优质云手机品牌&#xff0c;帮助您选择最适合的工具…...

基于openzeppelin插件的智能合约升级

一、作用以及优点 部署可升级合约&#xff0c;插件自动部署proxy和proxyAdmin合约&#xff0c;帮助管理合约升级和交互&#xff1b;升级已部署合约&#xff0c;通过插件快速升级合约&#xff0c;脚本开发方便快捷&#xff1b;管理代理管理员的权限&#xff0c;只有proxyAdmin的…...

WGAN生成对抗网络数据生成

数据生成 | WGAN生成对抗网络数据生成 目录 数据生成 | WGAN生成对抗网络数据生成生成效果基本描述程序设计参考资料 生成效果 基本描述 1.WGAN生成对抗网络&#xff0c;数据生成&#xff0c;样本生成程序&#xff0c;MATLAB程序&#xff1b; 2.适用于MATLAB 2020版及以上版本&…...

SQL面试题——拼多多SQL面试题 求连续段的起始位置和结束位置

拼多多SQL面试题 求连续段的起始位置和结束位置 今天的题目来自拼多多,我们先看一下题目描述 有一张表ids记录了id,id不重复,但是会存在间断,求出连续段的开始位置和结束位置 +---+ | id| +---+ | 1| | 2| | 3| | 5| | 6| | 8| | 10| | 12| | 13| | 14| | 15| +--…...

Contextual Affinity Distillation for Image Anomaly Detection

Contextual Affinity Distillation for Image Anomaly Detection 日本东北大学 摘要 先前对无监督工业异常检测的研究主要通过匹配或学习局部特征表示来关注“结构”类型的异常&#xff0c;例如裂纹和颜色污染。虽然在这种异常上实现了显着的高检测性能&#xff0c;但他们面…...

如何在HTML中修改光标的位置(全面版)

如何在HTML中修改光标的位置&#xff08;全面版&#xff09; 在Web开发中&#xff0c;控制光标位置是一个重要的技巧&#xff0c;尤其是在表单处理、富文本编辑器开发或格式化输入的场景中。HTML中的光标位置操作不仅适用于表单元素&#xff08;如<input>和<textarea…...

Spring Cloud Alibaba(六)

目录&#xff1a; 分布式链路追踪-SkyWalking为什么需要链路追踪什么是SkyWalkingSkyWalking核心概念什么是探针Java AgentJava探针日志监控实现之环境搭建Java探针日志监控实现之探针实现编写探针类TestAgent搭建 ElasticsearchSkyWalking服务环境搭建搭建微服务微服务接入Sky…...

Http请求系列---【http的几个请求时间分别代表什么?以及如何设置?】

在HTTP客户端编程中&#xff0c;通常涉及以下几种关键的超时设置&#xff1a; 连接超时 (connectTimeout)&#xff1a; 定义&#xff1a;在与服务器建立连接时等待的最大时间。这包括DNS解析时间、连接建立时间等。作用&#xff1a;如果在指定的时间内无法建立连接&#xff0c;…...

如何将CSDN博客下载为PDF文件

1.打开CSDN文章内容 2.按键盘上的f12键&#xff08;或者右键—审查元素&#xff09;进入浏览器调试模式&#xff0c;点击控制台&#xff08;Console&#xff09;进入控制台 3.在控制台输入以下代码&#xff0c;回车 4.在弹出的打印页面中将布局设置成横向&#xff0c;纵向会…...

关于IDEA 2024.2.1 Java EE 无框架配置Tomcat环境以及servlet使用教程

前言 这里的IDEA使用的是专业版&#xff0c;大学生认证后即可使用&#xff0c;社区版没有接触过暂不提&#xff0c;如果你是社区版&#xff0c;那么很可惜&#xff0c;本博客并不适用。本博客适用于java web刚入门的朋友学习使用&#xff0c;并不适用于高级部署。注意&#xf…...