Java反射机制深度解析:方法、实战与底层机制
大家好,我是钢板兽!
反射作为Java的特性,它不仅是Spring三大特性Ioc、DI、AOP的基础,而且MyBatis、Jackson序列化、rpc远程调用接口都用到了反射机制。
本文将带你系统性地掌握 Java 反射的使用,通过 JSON 反序列化的应用场景了解反射机制在实战中的使用,并通过JVM 底层实现深入剖析反射的底层机制。
文章目录
- 1.反射是什么?
- 2.反射的基本使用
- 2.1 获取Class<T>对象
- 2.2 获取类结构信息
- 2.3 操作结构信息
- 2.4 特殊处理
- 2.5 性能优化
- 3.反射的实战使用
- 3.1 JSON → Java 对象反序列化
- 3.2 依赖反射机制的后端技术栈
- 4.反射的底层机制
1.反射是什么?
反射(Reflection)是一种在运行时对程序“结构信息”访问与操作的机制。
Java是静态类型语言,其程序结构信息在编译器就已经确定好了,比如方法签名、字段类型、继承关系等。通过主动使用反射,编译器的结构信息可以被延伸到运行时,程序可以在运行时动态访问、读取甚至修改这些结构信息,从而实现对静态类型系统的动态扩展和运行期控制,突破编译器的静态绑定限制。
反射的底层实现依赖于**“运行时类元数据结构”**,JVM 加载每一个 .class
文件时,都会为其构造一份“类的运行时结构”,并定义在方法区的 InstanceKlass
中。这个运行时类结构包括:
信息项 | 说明 |
---|---|
类名、父类、接口名 | 支撑类的继承 |
字段表 | 字段名称、类型、修饰符、内存偏移量 |
方法表 | 方法签名、字节码入口、方法句柄 |
注解数据 | 保留注解的元数据 |
常量池 | 对类、方法、字段等的符号引用 |
2.反射的基本使用
JVM 只对外暴露一个 Java 层的对象 —— java.lang.Class<T>
,它是所有类元信息的唯一入口。
所以我们要先拿到 Class<?>
对象,才能访问类的结构。Class<?>
内部再通过 native 方法(本地方法)访问 JVM 结构,并包装成 Field
、Method
等反射对象,Field.get()
、Method.invoke()
等操作都依赖于这些对象所持有的 JVM 数据指针。
这决定了 Java 的反射操作流程具有顺序性,任何试图“越级访问”的操作都将失败或被安全机制禁止,使用反射的基本操作流程如下:
- 第一步:获取
Class<T>
对象。 - 第二步:获取类结构信息(字段、方法、构造器、注解等)
- 第三步:操作结构信息(创建对象/调用方法/设置字段)
其它操作:
- 特殊处理(私有访问、泛型、注解等高级特性)
- 性能优化(缓存反射对象、MethodHandle)
2.1 获取Class对象
Class<T>
对象的获取有三种方式:
-
通过类字面量(编译期已知)
Class<?> clazz1 = MyClass.class;
-
通过对象(运行时获取)
MyClass obj = new MyClass(); Class<?> clazz2 = obj.getClass();
-
通过类名字符串(支持动态加载)
Class<?> clazz3 = Class.forName("com.example.MyClass");
这种方式是获取
Class<T>
对象最典型的方式,常用于框架中动态加载类。
2.2 获取类结构信息
-
获取字段
Field[] fields = clazz.getDeclaredFields(); Field nameField = clazz.getDeclaredField("name");
-
获取方法
Method[] methods = clazz.getDeclaredMethods(); Method m = clazz.getDeclaredMethod("sayHello", String.class);
-
获取构造器
Constructor<?>[] constructors = clazz.getDeclaredConstructors(); Constructor<?> ctor = clazz.getDeclaredConstructor(String.class, int.class);
-
获取注解
Annotation[] annotations = clazz.getAnnotations(); boolean hasAnno = clazz.isAnnotationPresent(MyAnnotation.class); MyAnnotation ann = clazz.getAnnotation(MyAnnotation.class);
2.3 操作结构信息
-
创建对象实例
Object obj = clazz.getDeclaredConstructor().newInstance();
或者通过有参构造器:
Constructor<?> ctor = clazz.getDeclaredConstructor(String.class); Object obj = ctor.newInstance("Tom");
-
设置字段值 / 获取字段值
Field nameField = clazz.getDeclaredField("name"); nameField.setAccessible(true); // 如果是 private nameField.set(obj, "Jerry"); String name = (String) nameField.get(obj);
-
调用方法
Method method = clazz.getDeclaredMethod("sayHello", String.class); method.setAccessible(true); method.invoke(obj, "world");
invoke
方法是java.lang.reflect.Method
类的一个方法,用于动态调用某个对象的方法。Object invoke(Object obj, Object... args)
obj
:要在其上调用方法的对象(即目标实例),对于静态方法可以传null
。args
:方法参数的数组,如果无参方法可以传null
或空数组。
2.4 特殊处理
-
访问私有构造器、字段、方法
Java 的访问控制符(
private
、protected
、public
)在运行时依然生效,JVM 默认会检查访问权限,所以要主动绕过这一限制,这属于对反射行为的“增强”或“越权”。method.setAccessible(true);
-
获取泛型信息
Java 泛型采用类型擦除机制,在运行时大多数泛型信息已被擦除。
要访问泛型参数,必须通过反射中的
ParameterizedType
、TypeVariable
等复杂 API 解析。属于高级用法。Field listField = clazz.getDeclaredField("list"); Type type = listField.getGenericType(); // 获取该字段的通用类型(带泛型信息) if (type instanceof ParameterizedType) { // 判断该字段是否是一个参数化类型// 如果字段是参数化类型,那么取出其实际的泛型参数。Type[] actualTypes = ((ParameterizedType) type).getActualTypeArguments(); }
-
解析注解信息
Field field = clazz.getDeclaredField("name"); MyAnnotation annotation = field.getAnnotation(MyAnnotation.class); System.out.println(annotation.value());
2.5 性能优化
反射本质上是一种运行时动态调度机制,开销大(方法查找、访问检查、装箱/拆箱等),在实际框架/高性能场景中,需要引入一些性能优化的手段。
-
缓存反射对象
使用 Java 反射时,如
clazz.getDeclaredMethod(...)
或method.invoke(...)
,每次调用都涉及 元信息查找与访问权限检查,这在高频场景下性能较差。为了优化性能,可以将反射对象(如
Method
)缓存起来,避免重复查找,典型场景如:Spring、MyBatis、低代码平台中的动态组件绑定等。// 方法级缓存 private static final Map<String, Method> methodCache = new ConcurrentHashMap<>();// 如果缓存中没有 "sayHello",则调用 lambda 表达式创建并存入缓存;否则直接返回已有的 Method 对象。 Method m = methodCache.computeIfAbsent("sayHello", k -> {try {Method method = clazz.getDeclaredMethod("sayHello", String.class);method.setAccessible(true);return method;} catch (Exception e) {throw new RuntimeException(e);} });
-
使用
MethodHandle
替代Method.invoke
Method.invoke()
本质上是 JVM 内部通过反射执行的一种“间接调用”,存在性能劣势。Java 7 引入了java.lang.invoke
包,提供了更底层、更高效的方法句柄机制。MethodHandle
是对方法、构造器、字段访问的一种 可直接执行的指令句柄(类似函数指针),支持 JIT 内联优化,性能接近直接调用。// 获取当前类上下文的查找器,用于寻找类中的方法句柄 MethodHandles.Lookup lookup = MethodHandles.lookup(); // 查找实例方法,第一个参数是目标类;第二个是方法名;第三个是方法类型(返回值 + 参数类型)。 MethodHandle handle = lookup.findVirtual(MyClass.class, "sayHello", MethodType.methodType(void.class, String.class)); handle.invoke(obj, "World");
3.反射的实战使用
3.1 JSON → Java 对象反序列化
在后端服务中,几乎所有系统都会接收客户端发来的 JSON 请求,例如:
{"id": 123,"name": "Alice","age": 26
}
我们希望将这个 JSON 转换成如下实体类:
public class User {private int id;private String name;private int age;// getter / setter
}
但问题是:这段 JSON 是在运行时到达的,程序编译时并不知道要反序列化成哪个类、字段名是什么、字段类型是什么。
解决方案就是让前端提交任意 Java Bean 的类名 + JSON 内容,后端系统使用反射动态构造对象并设置字段完成反序列化。
前端请求示例:
POST /api/parse
Content-Type: application/json{"className": "com.example.User","json": "{"id": 123,"name": "Alice","age": 26}"
}
FastJSON / Jackson 中核心逻辑(简化版):
@PostMapping("/api/parse")
public String parseObject(@RequestBody Map<String, Object> request) throws Exception {String className = (String) request.get("className");String json = (String) request.get("json");// 这时候类名是运行时才知道的,必须用反射Class<?> clazz = Class.forName(className);// parseObject是阿里巴巴 FastJSON 框架 提供的 API,用于将一段 JSON 字符串反序列化为 Java 对象。Object obj = JSON.parseObject(json, clazz);// 假设我们统一调用 getName() 来检查反序列化是否成功Method getName = clazz.getMethod("getName");String name = (String) getName.invoke(obj);return "Parsed object name = " + name;
}
FastJSON 内部的JSON.parseObject(json, clazz)
内部会:
- 读取传入的
clazz
的所有字段(通过反射); - 对应字段名从 JSON 中取值;
- 自动进行类型转换(字符串转 int、Date 等);
- 通过反射赋值到字段上(使用
Field.set()
); - 最终返回被填充好的对象实例。
最后,obj
就是一个填充完属性的 User
实例了。
3.2 依赖反射机制的后端技术栈
在我们常用的一些后端技术栈中都“隐藏”着反射机制的身影,比如Spring框架、MyBatis、Dubbo/gRPC等。
(1)Spring框架
功能模块 | 使用方式 |
---|---|
IOC 容器 | 使用反射实例化 Bean,调用构造方法、Setter 方法注入属性 |
依赖注入(DI) | 通过 Field.set() 或 Method.invoke() 注入依赖字段或方法 |
AOP(面向切面编程) | 使用 JDK 动态代理 / CGLIB 生成代理对象,方法拦截点通过反射执行原始方法 |
注解驱动配置 | 反射读取 @Component , @Autowired , @Value , @Transactional 等注解 |
事件监听、条件配置 | 动态扫描标注方法和类,注册监听器和条件逻辑 |
Spring Expression Language(SpEL) | 使用反射读取对象结构以执行表达式 |
(2)MyBatis
功能点 | 说明 |
---|---|
Mapper 接口动态代理 | 使用 Proxy.newProxyInstance 创建接口代理对象 |
方法解析 | 拦截方法调用后,通过反射获取方法签名、注解等 |
参数处理器 | 反射分析参数对象,提取字段值写入 SQL 语句 |
返回值映射 | SQL 查询结果 → 实体类:通过反射设置字段值(Field.set() ) |
注解解析 | 解析 @Select , @Insert 等构建 SQL 映射 |
构造对象 | 执行查询后反射创建结果对象,支持构造器注入或默认构造方式 |
(3)Dubbo / gRPC
功能点 | 说明 |
---|---|
泛化调用(GenericService) | 客户端仅传入接口名、方法名、参数列表,服务端通过反射调用目标方法 |
JDK 动态代理 | 消费方创建接口代理对象,通过反射将调用封装为远程调用请求 |
服务暴露 | 服务提供者注册本地实现类,通过反射暴露其方法签名给注册中心 |
序列化 | 使用反射确定参数字段结构,用于 Hessian、Kryo 等序列化协议编解码 |
SPI 插件机制 | 利用 Class.forName() + 反射构造插件实例(比如扩展点、Filter、LoadBalance) |
(4) Jackson / Gson
功能点 | 说明 |
---|---|
字段遍历与读取 | 利用 Class.getDeclaredFields() 遍历对象属性,读取其值用于 JSON 输出 |
构造对象 | 反射调用默认构造方法或使用 Unsafe 构建无参对象用于反序列化 |
字段赋值 | 通过 Field.set() 将 JSON 数据写入 Java 对象 |
注解处理 | Jackson 解析 @JsonProperty , @JsonIgnore , @JsonInclude 等注解控制行为 |
泛型处理 | 利用 ParameterizedType 判断泛型结构(如 List<User> )并反射填充 |
4.反射的底层机制
使用反射的过程中底层机制是怎样的?本节以字段设置为例来探究反射的底层触发过程。
Class<?> clazz = MyClass.class;
Object obj = clazz.getDeclaredConstructor().newInstance(); // 创建 User 实例
Field field = clazz.getDeclaredField("id"); // 在当前 Class 对象中查找名称为 "id" 的字段
field.setAccessible(true);
field.set(obj, 100);
逐行分析每行代码实际发生了什么。
(1)Class<?> clazz = MyClass.class
这是 Java 层访问类的元模型对象。在 JVM 内部,每一个 .class
文件被加载后都会生成一个 Class<?>
实例,它是对 JVM 内部 InstanceKlass
的封装。
Class
是 Java 层对象;InstanceKlass
是 JVM 内部 C++ 层结构,保存字段表、方法表、注解信息、常量池等;- 每个
Class<?>
对象都通过 native handle 关联到对应的InstanceKlass
。
(2)Object obj = clazz.getDeclaredConstructor().newInstance()
这个操作等价于:
Constructor<?> constructor = clazz.getDeclaredConstructor(); // 找无参构造器
Object obj = constructor.newInstance(); // 调用构造器
底层执行逻辑:
- 查找构造方法(构造器也是一个
Method
,JVM 方法表中<init>
); - 创建实例对象:
- JVM 调用
Unsafe.allocateInstance()
或JVM_NewInstance()
; - 在堆中分配内存空间,初始化对象头;
- JVM 调用
- 调用
<init>
构造方法初始化字段。
(3)Field field = clazz.getDeclaredField("id")
这是反射获取字段的核心步骤,JVM 底层执行过程:
Class.getDeclaredField(name)
是 Java 层接口;- 内部通过 JNI(Java本地接口) 调用 native 方法
Class.getDeclaredField0
; InstanceKlass::_fields
表中保存所有字段结构,包括字段名、类型、修饰符、slot(编号);- 查找字段名
"id"
对应的fieldInfo
; - 构造一个 Java 层
Field
对象进行封装,保留:- 字段名;
- 字段类型;
- 父类;
- 字段在对象内存中的偏移(
fieldOffset
);
源码参考:
// HotSpot C++ 层结构
class InstanceKlass {Array<FieldInfo*>* fields(); // 包含字段名、偏移、类型等
}
(4)field.setAccessible(true)
该操作本质是关闭 Java 语言的访问控制检查(绕过 private/protected 限制),实际机制:
- 设置
Field
对象的override
标志; - 会影响后续
Field.get()
、set()
时是否进行权限校验; - 在 Java 9+ 中受到模块系统限制,调用需要
--add-opens
启动参数支持。
(5) field.set(obj, 100)
这是整个反射调用中最重要的一步 —— 写入字段值,底层机制:
-
首次调用
field.set(...)
时,JDK 会通过Field.getFieldAccessor()
创建一个FieldAccessor
实例。该对象用于封装字段读写逻辑,并在之后缓存复用,具体调用路径如下:FieldAccessor
是一个接口,JDK 内部提供多个实现,包括基于字节码生成的访问器(如GeneratedFieldAccessor
) 和基于Unsafe
的低层访问器;为了优化性能,JDK 会尝试动态生成字节码(通过
MethodAccessorGenerator
),将字段访问逻辑转化为专门的MethodHandle
或代理类。 -
字段写入最终会走到底层内存操作逻辑,目前在 JDK 中有两种主流实现路径:
- 通过 JNI native 方法调用 JVM 内部逻辑,VM 提供一系列 native 方法处理字段写入,例如:
JVM_SetField(env, jclass clazz, jobject obj, jfieldID fieldID, jvalue val);
其内部调用 C++ 实现,找到对象引用
obj
,结合fieldID
(字段的唯一标识符),将值写入目标字段内存。- 通过
sun.misc.Unsafe
直接写入对象内存
JDK 中对性能要求较高的反射路径会绕过 JNI,直接调用 Unsafe,它是一个提供低层次、绕过 JVM 安全检查的操作能力的类,常被称为“JVM 的后门”。
UNSAFE.putInt(obj, offset, 100);
putInt
等方法会通过内存屏障和 CPU 指令直接修改堆中字段值。 -
JVM 中的对象实例在堆内存中的布局大致如下:
JVM 通过计算
obj
的堆内地址加上字段偏移量,即obj + offset
,精准定位该字段的物理存储地址,并完成写入操作。
field.set(obj, 100)
的执行流程代表了 Java 反射机制中典型的“元数据访问 → 方法调度 → 内存写入”三层架构:
- 利用
Field
封装结构信息; - 通过
FieldAccessor
访问分发; - 以
Unsafe
或 native 方法在对象内存中完成实际字段写入。
这个过程在代码层面虽然很简单,但它的运行路径跨越了 Java 层、JVM native 层与内存操作层,是 Java 反射机制的底层体现。
如果这篇文章对你有帮助,欢迎点赞、转发、留言!
相关文章:
Java反射机制深度解析:方法、实战与底层机制
大家好,我是钢板兽! 反射作为Java的特性,它不仅是Spring三大特性Ioc、DI、AOP的基础,而且MyBatis、Jackson序列化、rpc远程调用接口都用到了反射机制。 本文将带你系统性地掌握 Java 反射的使用,通过 JSON 反序列化的…...
查看wifi密码
netsh wlan show profile nameCMCC-Rkt_Wi-Fi5 keyclear CMCC-Rkt_Wi-Fi5是无线网名称...
RPC 发展史
RPC 发展史 RPC(Remote Procedure Call)即远程过程调用,随着微服务的兴起,每个服务都拥有自己的数据库,负责各自的模块,例如 keystone(认证服务)负责用户信息、权限认证的内容&…...
蓝桥杯基础算法-递归
代码简洁,但涉及到的运算,会随着递归层数的增加成指数级增长 路分析:第20行20列位于45度这条线上 这条线上的数字是1 5 13 25 41...两数之差:4 8 12 16 --->每一个都是在前面的基础上4,可以用递归或者循环 public class dem…...
山东大学离散数学第七章习题解析
参考教材:离散数学教程,徐秋亮 / 栾俊峰 / 卢雷 / 王慧 / 赵合计 编著,山东大学计算机科学与技术学院 注:该解析为个人所写,涵盖了 2022-2023-2 学期赵合计老师所布置的所有课本习题;由于学识、认识及经验…...
关于使用python 安装 flask-openapi3扩展,使用docker 环境的完整复盘
在某个时刻 需要运行python 3 flask-openapi3扩展 当前因为服务器为国产化服务器,操作系统版本为麒麟,python 版本为3.7 因为要安装flask-openapi3 包 又因为flask 版本小于2.0 from flask_openapi3 import OpenAPI,Info,Tag目前安装的是 …...
MybatisPlus的一些基本操作
mybatisplus分页 Testvoid testpage(){IPage<User> page new Page<>(1,3); userDao.selectPage(page,null);System.out.println("当前页码值:"page.getCurrent());System.out.println("每页显示数:"page.getSize());S…...
debian12安装mysql5.7.42(deb)
安装 官方文档 https://dev.mysql.com/doc/mysql-installation-excerpt/8.0/en/linux-installation-debian.html 上面是8.0的教程,服了我说怎么那么奇怪 5.7官方教程 https://dev.mysql.com/doc/mysql-installation-excerpt/5.7/en/linux-installation-debian.html …...
基于Python脚本实现Flink on YARN任务批量触发Savepoint的实践指南
基于Python脚本实现Flink on YARN任务批量触发Savepoint的实践指南 一、背景与价值 在流计算生产环境中,Flink on YARN的部署方式凭借其资源管理优势被广泛采用。Savepoint作为Flink任务状态的一致性快照,承载着故障恢复、版本升级、作业暂停等重要场景…...
Winform入门进阶企业级开发示例:http接口数据清洗转换、断线续传、mqtt数据传输实例详解(附代码资源下载)
场景 C#/Winform入门、进阶、强化、扩展、知识体系完善等知识点学习、性能优化、源码分析专栏分享: C#/Winform入门、进阶、强化、扩展、知识体系完善等知识点学习、性能优化、源码分析专栏分享_winform 强化学习-CSDN博客 如何将以上相关理论知识学以致用。下面针对Winform…...
PHP开发效率提升利器:通义灵码在VSCode中的应用与技巧
引言 在 PHP 开发领域,提高编码效率和质量是每位开发者追求的目标。通义灵码,作为一款由阿里云技术团队开发的智能编码助手,能够通过其强大的 AI 能力,为 PHP 开发者提供包括代码自动补全、智能注释、代码优化等多方面的支持。本…...
WHAT - React 错误边界处理 - react-error-boundary
目录 安装使用方式常用 Props使用场景 react-error-boundary 是一个由 Brian Vaughn 开发的 React 组件库,用于更方便地处理组件树中的错误(错误边界)。 阅读参考: React Error Boundariesreact-error-boundary 安装 npm inst…...
数据模型评估的四维黄金法则:从技术验证到业务价值证明
引言:为什么你的数据模型总被质疑? 在滴滴出行的一次核心业务会议上,数据团队与业务部门爆发了激烈争论:新上线的订单预测模型是否真的优于旧系统?数据工程师认为查询速度提升40%已是巨大成功,业务方却质疑…...
vscode ctrl+鼠标左键不能跳转
笔者使用的vscode版本是1.85.2(一周前从1.99降下来的,因为版本过高连不上服务器)。 使用python时突然发现代码看起来有些别扭,细看之下发现是import xxx语句中的包的颜色从之前的青色变成了现在的白色。再用ctrl左键点击包名试图…...
换动态IP对电脑有什么影响:全面解析与实用指南
在当今数字化时代,IP地址作为网络世界的"身份证",对我们的网络体验有着重要影响。许多用户出于某些原因,会考虑更换动态IP地址。那么,这种操作究竟会对我们的电脑产生哪些影响?是利大于弊还是弊大于利&#…...
Go语言从零构建SQL数据库(6) - sql解析器(番外)- *号的处理
番外:处理SQL通配符查询 在SQL中,SELECT * FROM table是最基础的查询之一,星号(*)是一个通配符,表示"选择所有列"。虽然通配符查询看起来简单,但在解析器中需要特殊处理。下面详细介…...
大模型推理引擎选型与应用场景分析:SGLang、Ollama、VLLM 和 LLaMA.cpp
在当下的大模型技术生态中,SGLang、Ollama、VLLM 和 LLaMA.cpp 各具特色,适用于不同的应用场景和用户需求。以下是它们的核心特点及适用场景的深度剖析: 1. SGLang:高性能企业级推理引擎 核心优势: 零开销批处理&…...
参考平面跨分割情况下的信号回流
前言:弄清楚信号的回流路径,是学习EMC和高速的第一步! 如果我们不管信号的回流路径,会造成什么后果?1、信号完整性问题,信号的回流路径不连续会导致信号反射、衰减和失真。2、信号衰减和噪声干扰ÿ…...
Vue2下载二进制文件
后端: controller: GetMapping(value "/get-import-template")public void problemTemplate(HttpServletRequest request, HttpServletResponse response) throws Exception {iUserService.problemTemplate(request, response);} service: void probl…...
AnimateCC基础教学:随机抽取花名册,不能重复
一.核心代码: this.btnStartObj.addEventListener("click", switchBtn); this.btnOkObj.addEventListener("click", oKBtn); createjs.Ticker.addEventListener("tick", updateRandom); var _this this; var nameArr ["张三", &quo…...
windows+cmake+vscode+NDK远程调试安卓端C++项目
windowscmakevscodeNDK远程调试安卓端C项目 windowscmakevscodeNDK远程调试安卓端C项目 windowscmakevscodeNDK远程调试安卓端C项目 使用C开发安卓端算法库时,需要使用NDK进行交叉编译。使用NDK编译代码时,需要编写.mk脚本进行代码的编译和链接…...
大语言模型(LLM)全解析:从原理到实战应用
在人工智能飞速发展的今天,大语言模型(LLM)已成为改变我们工作生活的重要技术。无论是ChatGPT的对话能力,还是DeepSeek的文本处理,背后都离不开LLM的强大支持。本文将用通俗易懂的语言,带您全面了解LLM的工作原理、训练方法、优化…...
Qt 入门 4 之标准对话框
Qt 入门 4 之标准对话框 Qt提供了一些常用的对话框类型,它们全部继承自QDialog类,并增加了自己的特色功能,比如获取颜色、显示特定信息等。下面简单讲解这些对话框,可以在帮助索引中查看Standard Dialogs关键字,也可以直接索引相关类的类名。 本文将以一个新的项目为主介绍不…...
PyTorch DataLoader 参数详解
在使用 PyTorch 的 DataLoader 时,有许多参数可以调整,这些参数能够帮助我们平衡数据加载效率、内存使用和训练过程的稳定性。下面介绍几个常用参数,并讲解它们的作用: dataset 含义: 数据集对象,必须实现 …...
PowerBI 计算时间用EDATE
我在原表基础上,根据日期字段,计算去年时间 CONCATENATEX(DISTINCT(SELECTCOLUMNS(VALUES(日期表),"去年", FORMAT(DATEADD([日期], -1, YEAR), "yyyyMM"))), [YearMonth],",") 我发现很奇怪的现象,假如某个日…...
GRBL运动控制算法(四)加减速运算
前言 在数控系统和运动控制领域,GRBL 作为一款高效、轻量化的开源固件,因其卓越的性能和简洁的架构被广泛应用于各类嵌入式运动控制场景。GRBL加减速算法的实现尤为关键——它直接决定了运动控制的精度、效率与设备稳定性。 本文深入解析加减速运算的核…...
CSS 学习提升网站或者项目
有几个不错的开源项目可以帮助你练习和提升CSS技能: CSS-Tricks CSS-Tricks 提供了很多关于CSS的技巧和教程,可以通过实践它们来提高CSS技能。你可以在CSS-Tricks上找到很多有趣的项目和代码示例。 Frontend Mentor Frontend Mentor 是一个非常适合练习…...
PolarDB 读已提交事务隔离级别 select ... for update, where条件未用索引,查不到数据的时候不会锁表
由于没有给字段设置唯一性,所以改为通过查询语句加锁确保唯一性,但是发现select count(*) 为0时,不会加锁,所以在insert方法后面需要加锁二次查询确保唯一性。 在 PolarDB 的读已提交事务隔离级别下,SELECT ... FOR UP…...
Python基础——Matplotlib库
绘图基础 Matplotlib 库太大,画图通常仅仅使用其中的核心模块 matplotlib.pyplot,并给其一个别名 plt,即 import matplotlib.pyplot as plt。为了使图形在展示时能很好的嵌入到 Jupyter 的 Out[ ] 中,需要使用%matplotlib inline…...
群晖Hyper Backup备份的东西怎么还原?
一、背景 前面写了一篇文章关于群晖NAS中最简单的备份方案,Hyper Backup 方案 群晖NAS最简单的备份教程(只备份需要的目录到不同的硬盘),留了个尾,即怎么还原备份的东西,这里完结一下。 二、还原方案 2.…...
记录IBM服务器检测到备份GPT损坏警告排查解决过程
服务器设备:IBM x3550 M4 Server IMM默认IP地址:192.168.70.125 用户名:USERID 密码:PASSW0RD(注意是零0) 操作系统:Windows Hyper-V Server 2016 IMM Web System Status Warning࿱…...
蓝桥杯嵌入式十五届模拟二(串口DMA,占空比的另一种测量方式)
一.LED 先配置LED的八个引脚为GPIO_OutPut,锁存器PD2也是,然后都设置为起始高电平,生成代码时还要去解决引脚冲突问题 二.按键 按键配置,由原理图按键所对引脚要GPIO_Input 生成代码,在文件夹中添加code文件夹&#…...
22 | 如何继续提升 Go 开发技术?
提示: 所有体系课见专栏:Go 项目开发极速入门实战课;欢迎加入 云原生 AI 实战营 星球,12 高质量体系课、20 高质量实战项目助你在 AI 时代建立技术竞争力(聚焦于 Go、云原生、AI Infra)。 「Go 项目开发极速…...
一文详解OpenCV环境搭建:Windows使用CLion配置OpenCV开发环境
在计算机视觉和图像处理领域,OpenCV 是一个不可或缺的工具。其为开发者提供了一系列广泛的算法和实用工具,支持多种编程语言,并且可以在多个平台上运行。对于希望在其项目中集成先进视觉功能的开发者来说,掌握如何配置和使用OpenC…...
云原生周刊:深入探索 kube-scheduler-simulator
开源项目推荐 mcp-server-kubernetes mcp-server-kubernetes 是一个实现了模型上下文协议(MCP)的服务器,旨在通过自然语言与 K8s 集群进行交互。它支持连接到 K8s 集群,列出所有 Pod、服务、部署和节点,创建、描述、…...
总结一下常见的EasyExcel面试题
说一下你了解的POI和EasyExcel POI(Poor Obfuscation Implementation):它是 Apache 软件基金会的一个开源项目,为 Java 程序提供了读写 Microsoft Office 格式文件的功能,支持如 Excel、Word、PowerPoint 等多种文件格…...
【Java设计模式】第2章 UML急速入门
2-1 本章导航 UML类图与时序图入门 UML定义 统一建模语言(Unified Modeling Language):第三代非专利建模语言。特点:开放方法,支持可视化构建面向对象系统,涵盖模型、流程、代码等。UML分类(2.2版本) 结构式图形:系统静态建模(类图、对象图、包图)。行为式图形:事…...
Excel处理控件Spire.XLS系列教程:C# 设置 Excel 中的数字格式
在 Excel 工作表中,原始数据通常显示为缺乏直观性的普通数字。通过设置数字格式,可以将这些数字转换成更容易理解的形式。例如,将销售额数据设置为货币格式,即添加货币符号和千位分隔符,可使所代表的金额一目了然。将市…...
脚本启动 Java 程序
如果你想在后台启动一个 Java 程序,并在终端窗口中显示一个自定义的名字,可以通过编写一个简单的脚本来实现。以下是一个基于 Linux/macOS 的解决方案,使用 Bash 脚本启动 Java 程序,并在终端窗口中显示自定义标题。 示例脚本 创建…...
UniappX动态引入在线字体图标,不兼容css时可用。
优缺点 优点:不需要占用本地存储,可直接在线同步库图标,不用再手动引入ttf文件,不用手动添加键值对对应表。 缺点:受网速影响,字体库cdn路径可能会更改,ios端首次加载,可能会无图标…...
机器学习 | 强化学习基本原理 | MDP | TD | PG | TRPO
文章目录 📚什么是强化学习🐇监督学习 vs 强化学习🐇马尔科夫决策过程(MDP)📚基本算法(value-based & policy-based)🐇时序差分算法(TD)🐇SARSA和Q-learning🐇策略梯度算法(PG)🐇REINFORCE和Actor-Critic🐇信任区域策略优化算法(TRPO)学习视频…...
k8s之Service类型详解
1.ClusterIP 类型 2.NodePort 类型 3.LoadBalancer 类型 4.ExternalName 类型 类型为 ExternalName 的 Service 将 Service 映射到 DNS 名称,而不是典型的选择算符, 例如 my-service 或者 cassandra。你可以使用 spec.externalName 参数指定这些服务…...
AI平台如何实现推理?数算岛是一个开源的AI平台(主要用于管理和调度分布式AI训练和推理任务。)
数算岛是一个开源的AI平台,主要用于管理和调度分布式AI训练和推理任务。它基于Kubernetes构建,支持多种深度学习框架(如TensorFlow、PyTorch等)。以下是数算岛实现模型推理的核心原理、架构及具体实现步骤: 一、数算岛…...
linux开发环境
1.虚拟机环境搭建 在 Ubuntu 系统中,打开(如图中显示的窗口 )常见快捷键有: Ctrl Alt T:这是最常用的打开终端的快捷键组合 ,按下后会快速弹出一个新的终端窗口。 在 VMware 虚拟机环境中,若…...
OSPF复习
OSPF OSPF---开放最短路径优先协议 动态路由判定依据:选路,收敛速度,占用资源 OSPFV2和RIPV2的相同点: 1.都是无类别的路由协议; 2.都是通过组播来传播信息的;(RIP:224.0.0.9&am…...
AWS S3深度剖析:云存储的瑞士军刀
1. 引言 在当今数据驱动的世界中,高效、可靠、安全的数据存储解决方案至关重要。Amazon Simple Storage Service (S3)作为AWS生态系统中的核心服务之一,为企业和开发者提供了一个强大而灵活的对象存储平台。本文将全面解析S3的核心特性,帮助读者深入理解如何充分利用这一&q…...
pyTorch中 tensorboard的使用
目录 01.导包、 transforms数据转化、torchvision数据集、创建dataloaders、展示图片的封装函数 02定义模型 03定义损失函数与优化器 1.tensorboard的安装 2.tensorboard的使用 2.1添加图片 2.2 添加模型结构图 2.3 添加损失的变化 #pyTorch中的tensorboard 与 tens…...
Android audio(2)-audioservice
AudioService是Android的系统服务(systemservice),由SystemServer负责启动。提供Android APK 所需的非数据通路(playback/capture)相关的audio 功能实现,是binder通信中的server端,与之对应的 C…...
星城幻境:科技与千年文脉的交响诗-长沙
故事背景 故事发生在中国湖南长沙,通过六个充满未来感的城市景观,展现人工智能修复古建筑、生态摩天楼、全息水幕许愿等场景,描绘科技赋能下历史文脉与未来城市的共生图景。 故事内容 从岳麓书院清晨的智能修复到湘江夜空的数字烟花ÿ…...
记录学习的第二十三天
老样子,每日一题开胃。 我一开始还想着暴力解一下试试呢,结果不太行😂 接着两道动态规划。 这道题我本来是想用最长递增子序列来做的,不过实在是太麻烦了,实在做不下去了。 然后看了题解,发现可以倒着数。 …...