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

Java进阶six junit单元测试,反射,注解,动态代理

前言

Java进阶课程的第六篇,也是最后一篇,junit单元测试,反射,注解,动态代理相关内容


包含知识点

 junit单元测试
反射

1.内部类Student:

包含私有/公共字段和方法

包含默认构造器和私有构造器

2.获取Class对象的三种方式:

.class 语法直接获取

通过对象实例的getClass()方法获取

最常用的Class.forName()动态加载方式

3.反射创建对象:

通过无参构造器创建实例

访问私有构造器创建实例(需要设置setAccessible(true))

4.字段操作:

访问公共字段直接修改值

访问私有字段需要设置可访问权限

5.方法调用:

调用公共方法

调用私有方法需要设置可访问权限

演示带参数方法的调用

6.类结构信息获取:

获取类名和方法列表

区分getMethods()和getDeclaredMethods()的区别

7.关键点说明:

setAccessible(true)可以突破私有成员的访问限制,但会破坏封装性

反射操作需要处理各种异常(本示例直接抛出简化代码)

反射的性能较低,适合框架开发等需要高度灵活性的场景

反射可以访问到类的完整结构信息,包括注解、泛型等

注解

1.自定义注解:
使用@interface关键字来定义一个新的注解类型。例如:public @interface MyInterface {}。
注解可以包含成员变量(也称作元素),这些成员变量可以有默认值或必须在使用时提供值。
元注解(Meta-annotations):
@Target指定注解的应用目标(如方法、字段等)。例如:@Target({ElementType.METHOD})表示该注解只能应用于方法上。
@Retention定义了注解的生命周期,RetentionPolicy.RUNTIME表示该注解将在运行时保留,可以通过反射读取。
2.注解的使用:
注解可以直接应用到类、方法或字段上,通过在它们之前加上注解名称并提供必要的参数值。例如:@MyTest(count = 2)。
3.反射与注解:
利用Java的反射机制,可以在运行时检查类、方法或字段上的注解。例如,通过method.isAnnotationPresent(MyTest.class)判断方法是否被特定注解标记,并通过method.getDeclaredAnnotation(MyTest.class)获取注解实例。
反射还可以用于调用带有注解的方法,如示例中method.invoke(ad)执行被@MyTest注解标记的方法。
4.注解属性的默认值:
注解成员可以设置默认值,如果在使用注解时不提供值,则会使用默认值。例如:int count() default 1;。
5.特殊属性value:
如果注解只有一个名为value的成员,在使用注解时可以省略成员名直接提供值。例如:@MyInterface("delete")相当于@MyInterface(value="delete")。

动态代理

1.业务接口 (UserService)

定义代理类和真实类共同遵守的规范

动态代理只能基于接口实现

2.真实对象 (UserServiceImpl)

实际业务逻辑的实现类

包含需要被增强的核心逻辑

3.调用处理器 (LoggingHandler)

实现InvocationHandler接口

持有真实对象引用(目标对象)

invoke()方法中实现统一代理逻辑

通过反射调用真实方法(method.invoke())

可以添加前置/后置增强逻辑(如日志、事务等)

4.代理对象创建 (Proxy.newProxyInstance)

参数1:类加载器(通常使用接口的类加载器)

参数2:代理类需要实现的接口数组

参数3:调用处理器实例

返回实现指定接口的代理对象

5.动态代理特点:

运行时动态生成代理类(通过ProxyGenerator生成)

代理类名通常为$Proxy+数字

继承Proxy类(所以不能代理类,只能代理接口)

实现了指定的业务接口

方法调用会被路由到InvocationHandler

6.典型应用场景:

AOP编程(日志、事务、权限控制)

RPC框架调用

服务接口的监控统计

单元测试Mock对象

7.注意事项:

代理对象的方法调用都会经过invoke方法

在invoke方法中谨慎使用proxy参数,容易引发递归调用

性能相比静态代理略低(反射调用)

无法代理final类和final方法


具体代码

 junit单元测试
package ADV_0;import org.junit.Test;class StringUtil {//业务类的一个方法public static void printNumber(String name){if(name == null){System.out.println("参数为null");return;}System.out.println("名字长度是:" + name.length());}
}// 测试类:junit单元测试框架,对业务类方法进行测试
public class StringUtilTest {// 测试方法:必公开public,无参,无返回值// 测试方法必须加上@Test注解(Junit核心)@Testpublic void testPrint() {StringUtil.printNumber("微光zc"); // 5// 测试用例,测试核心,各种情况下的测试StringUtil.printNumber("");StringUtil.printNumber(null);}
}
反射
package ADV_0;import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;/*** Java反射机制示例类* 演示如何通过反射操作类信息、创建对象、访问字段和调用方法*/
public class ADVZc5 {// 示例用内部类static class Student {private String name;public int age;public Student() {this.name = "Default";this.age = 18;}private Student(String name) {this.name = name;this.age = 20;}public void showInfo() {System.out.println("Student: " + name + ", " + age);}private void setAge(int age) {this.age = age;}}public static void main(String[] args) throws Exception {System.out.println("加载类,获取类的字节码:Class对象");System.out.println("获取类的构造器:Constructor对象");System.out.println("获取类的成员变量:Field对象");System.out.println("获取类的成员方法:MMethod对象");// 1. 获取Class对象的三种方式// 方式一:通过类名.class获取Class<Student> clazz1 = Student.class;// 方式二:通过对象.getClass()获取Student student = new Student();Class<? extends Student> clazz2 = student.getClass();// 方式三:通过Class.forName()获取(最常用)Class<?> clazz3 = Class.forName("ADV_0.ADVZc6$Student"); // 内部类需要用$符号System.out.println("三个Class对象是否相同:" + (clazz1 == clazz2 && clazz2 == clazz3));// 2. 通过反射创建对象// 使用无参构造器Constructor<?> constructor1 = clazz1.getDeclaredConstructor();Student s1 = (Student) constructor1.newInstance();s1.showInfo();// 使用私有构造器(需要设置可访问)Constructor<?> constructor2 = clazz1.getDeclaredConstructor(String.class);constructor2.setAccessible(true); // 突破私有访问限制Student s2 = (Student) constructor2.newInstance("Alice");s2.showInfo();// 3. 访问字段// 访问公共字段Field ageField = clazz1.getField("age");ageField.set(s1, 25); // 等价于 s1.age = 25System.out.print("修改公共字段后:");s1.showInfo();// 访问私有字段(需要设置可访问)Field nameField = clazz1.getDeclaredField("name");nameField.setAccessible(true);nameField.set(s1, "Bob"); // 等价于 s1.name = "Bob"System.out.print("修改私有字段后:");s1.showInfo();// 4. 调用方法// 调用公共方法Method showInfoMethod = clazz1.getMethod("showInfo");System.out.print("反射调用方法:");showInfoMethod.invoke(s2);// 调用私有方法(需要设置可访问)Method setAgeMethod = clazz1.getDeclaredMethod("setAge", int.class);setAgeMethod.setAccessible(true);setAgeMethod.invoke(s2, 30);System.out.print("修改私有字段后:");s2.showInfo();// 5. 获取类结构信息System.out.println("\n类结构信息:");System.out.println("类名:" + clazz1.getName());System.out.println("简单类名:" + clazz1.getSimpleName());System.out.println("公共方法列表:");for (Method method : clazz1.getMethods()) {System.out.println("  " + method.getName());}System.out.println("声明字段列表:");for (Field field : clazz1.getDeclaredFields()) {System.out.println("  " + field.getName());}System.out.println("===反射的基本作用===");// 1、类的全部成分的获取// 2、可以破坏封装性// 3、可以绕过泛型的约束System.out.println("===反射的应用:做框架的通用技术===");}
}
注解
package ADV_0;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;public class ADVZc6 {// 自定义注解public @interface MyInterface {String name();int age() default 18;String[] address();}
}@Target({ElementType.METHOD}) // 表示注解的作用目标为方法
@Retention(RetentionPolicy.RUNTIME) // 表示注解的保留策略: 编译器运行时(一直活着)
@interface MyTest {int count() default 1; // 表示注解的属性
}
@Target({ElementType.METHOD, ElementType.FIELD}) // 表示注解的作用目标为方法,成员变量
@Retention(RetentionPolicy.RUNTIME) // 表示注解的保留策略: 编译器运行时(一直活着)
@interface MyTest1 {
}@Target({ElementType.METHOD, ElementType.TYPE}) // 表示注解的作用目标为方法,成员变量
@Retention(RetentionPolicy.RUNTIME) // 表示注解的保留策略: 编译器运行时(一直活着)
@interface MyTest2 {String value();double height() default 169.5;String[] address();
}@ADVZc6.MyInterface(name = "赵丽颖", age = 18, address = {"北京", "上海"})
//@MyInterface(age = "delete")
//@MyInterface("delete") // 特殊属性value,在使用时如果只有一个value属性,value名称可以不写
class AnnotationDemo1 {@ADVZc6.MyInterface(name = "王菲", age = 52, address = {"北京", "香港"})public static void main( String[] args ) {// 目标:自定义注解。int a;}
}//@MyTest1
class AnnotationDemo2 {private int age;//@MyTest1public AnnotationDemo2(){}public static void main(String[] args) {//元注解的作用}public void getAgeTest(){}
}class AnnotationDemo4 {// 注解的应用场景:模拟junit框架。有MyTest注解的方法就执行,没有的就不执行public static void main(String[] args) throws Exception {AnnotationDemo4 ad = new AnnotationDemo4();// 1、获取类对象Class c = AnnotationDemo4.class;// 2、获取所有方法Method[] methods = c.getMethods();// 3、遍历所有方法,判断方法上是否有MyTest注解,有就执行,没有就不执行。for (Method method : methods) {// 4、判断方法上是否有MyTest注解if (method.isAnnotationPresent(MyTest.class)) {// 获取到这个方法的注解MyTest myTest = method.getDeclaredAnnotation(MyTest.class);int count = myTest.count();// 5、有就执行这个method方法for (int i = 0; i < count; i++) {method.invoke(ad);}}}}// 测试方法:public 无参 无返回值@MyTestpublic void test1(){System.out.println("test1方法执行了");}public void test2(){System.out.println("test2方法执行了");}@MyTest(count = 2)public void test3(){System.out.println("test3方法执行了");}@MyTestpublic void test4(){System.out.println("test4方法执行了");}
}
package ADV_0;import org.junit.Test;import java.lang.reflect.Method;
import java.util.Arrays;public class AnnotationDemo3 {//解析注解@Testpublic void parseClass() throws Exception {// 1.获取类对象Class c1 = Demo.class;// 2、使用isAnnotationPresent判断这个类上是否陈列了注解MyTest2if (c1.isAnnotationPresent(MyTest2.class)) {// 3、获取注解对象MyTest2 myTest2 = (MyTest2) c1.getDeclaredAnnotation(MyTest2.class);// 4、获取注解属性值String[] address = myTest2.address();double height = myTest2.height();String value = myTest2.value();// 5、打印注解属性值System.out.println(Arrays.toString(address));System.out.println(height);System.out.println(value);}}@Testpublic void parseMethod() throws Exception {// 1.获取类对象Class c1 = Demo.class;// 2、获取方法对象Method method = c1.getMethod("go");// 3、使用isAnnotationPresent判断这个方法上是否陈列了注解MyTest2if (method.isAnnotationPresent(MyTest2.class)) {// 4、获取注解对象MyTest2 myTest2 = method.getDeclaredAnnotation(MyTest2.class);// 5、获取注解属性值String[] address = myTest2.address();double height = myTest2.height();String value = myTest2.value();// 6、打印注解属性值System.out.println(Arrays.toString(address));System.out.println(height);System.out.println(value);}}
}
动态代理
package ADV_0;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;/*** 动态代理示例代码* 包含:接口定义、真实对象、调用处理器、客户端演示*/
public class ADVZc7 {// 1. 定义业务接口interface UserService {void addUser(String username);String getUser(int userId);}// 2. 真实对象(被代理类)static class UserServiceImpl implements UserService {@Overridepublic void addUser(String username) {System.out.println("真实方法: 添加用户 " + username);}@Overridepublic String getUser(int userId) {return "真实用户" + userId;}}// 3. 调用处理器(实现InvocationHandler)static class LoggingHandler implements InvocationHandler {private final Object target;  // 持有真实对象引用public LoggingHandler(Object target) {this.target = target;}/*** 代理方法调用的核心逻辑* @param proxy  代理对象(慎用)* @param method 被调用的方法对象* @param args   方法参数*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 前置增强System.out.println("[日志] 开始执行方法: " + method.getName());// 反射调用真实对象的方法Object result = method.invoke(target, args);// 后置增强System.out.println("[日志] 方法执行完成: " + method.getName());return result;}}public static void main(String[] args) {// 4. 创建真实对象UserService realService = new UserServiceImpl();// 5. 创建调用处理器InvocationHandler handler = new LoggingHandler(realService);// 6. 动态生成代理对象UserService proxyService = (UserService) Proxy.newProxyInstance(UserService.class.getClassLoader(), // 类加载器new Class[]{UserService.class},     // 代理接口数组handler                             // 调用处理器);// 7. 通过代理对象调用方法proxyService.addUser("张三");System.out.println("查询结果:" + proxyService.getUser(1001));// 打印代理类信息System.out.println("\n代理类名称: " + proxyService.getClass().getName());System.out.println("代理类父类: " + proxyService.getClass().getSuperclass());System.out.println("代理类实现的接口: ");for (Class<?> inter : proxyService.getClass().getInterfaces()) {System.out.println(" - " + inter.getName());}}
}

相关文章:

Java进阶six junit单元测试,反射,注解,动态代理

前言 Java进阶课程的第六篇&#xff0c;也是最后一篇&#xff0c;junit单元测试,反射,注解,动态代理相关内容 包含知识点 junit单元测试 反射 1.内部类Student&#xff1a; 包含私有/公共字段和方法 包含默认构造器和私有构造器 2.获取Class对象的三种方式&#xff1a; .…...

STM32 LED呼吸灯

接线图&#xff1a; 这里将正极接到PA0引脚上&#xff0c;负极接到GND&#xff0c;这样就高电平点亮LED&#xff0c;低电平熄灭。 占空比越大&#xff0c;LED越亮&#xff0c;占空比越小&#xff0c;LED越暗 PWM初始化配置 输出比较函数介绍&#xff1a; 用这四个函数配置输…...

栈和队列特别篇:栈和队列的经典算法问题

图均为手绘,代码基于vs2022实现 系列文章目录 数据结构初探: 顺序表 数据结构初探:链表之单链表篇 数据结构初探:链表之双向链表篇 链表特别篇:链表经典算法问题 数据结构:栈篇 数据结构:队列篇 文章目录 系列文章目录前言一.有效的括号(leetcode 20)二.用队列实现栈(leetcode…...

用一个例子详细说明python单例模式

单例模式是一种设计模式&#xff0c;它确保一个类只有一个实例&#xff0c;并提供一个全局访问点来访问该实例。这在需要控制资源&#xff08;如数据库连接、文件系统等&#xff09;的访问时非常有用。 下面是一个使用Python实现单例模式的例子&#xff1a; class Singleton:…...

Kotlin 委托详解

Kotlin 委托详解 引言 Kotlin 作为一种现代化的编程语言&#xff0c;在 Android 开发等领域得到了广泛的应用。在 Kotlin 中&#xff0c;委托&#xff08;Delegation&#xff09;是一种强大的特性&#xff0c;它可以让我们以更简洁的方式实现代码的复用和扩展。本文将详细解析…...

什么是词嵌入?Word2Vec、GloVe 与 FastText 的区别

自然语言处理(NLP)领域的核心问题之一,是如何将人类的语言转换成计算机可以理解的数值形式,而词嵌入(Word Embedding)正是为了解决这个问题的重要技术。本文将详细讲解词嵌入的概念及其经典模型(Word2Vec、GloVe 和 FastText)的原理与区别。 1. 什么是词嵌入(Word Em…...

2024年数据记录

笔者注册时间超过98.06%的用户 CSDN 原力是衡量一个用户在 CSDN 的贡献和影响力的系统&#xff0c;笔者原力值超过99.99%的用户 其他年度数据...

DBO优化最近邻分类预测matlab

蜣螂优化算法&#xff08;Dung Beetle Optimizer&#xff0c;简称 DBO&#xff09;作为一种新兴的群智能优化算法&#xff0c;于 2022 年末被提出&#xff0c;其灵感主要来源于蜣螂的滚球、跳舞、觅食、偷窃以及繁殖等行为。 本次使用的数据为 Excel 格式的分类数据集。该数据…...

Harbor 部署

harbor镜像仓库搭建 版本v2.10.3 文章目录 一. docker 安装 harbor1. harbor 配置http访问1.1 下载harbor二进制包1.2 修改配置文件1.3 运行1.4 访问 2.【可选】harbor 配置https访问2.1 自签证书2.1 修改配置文件2.3 修改hosts文件2.4 运行2.5 访问 二. k8s 安装harbor1 .安装…...

PSpice for TI体验

前言 基于 从零开始学 PSpice for TI 仿真工具 - 手把手操作实训课程_哔哩哔哩_bilibili 体验PSpice for TI的功能&#xff0c;并记录下来。文章内容大部分都参考自视频&#xff0c;可以理解成图文版。目前发现是没有支持中文语言&#xff0c;而且部分仿真&#xff0c;时间消耗…...

数据结构与算法 —— 常用算法模版

数据结构与算法 —— 常用算法模版 二分查找素数筛最大公约数与最小公倍数 二分查找 人间若有天堂&#xff0c;大马士革必在其中&#xff1b;天堂若在天空&#xff0c;大马士革必与之齐名。 —— 阿拉伯谚语 算法若有排序&#xff0c;二分查找必在其中&#xff1b;排序若要使用…...

苯乙醇苷类化合物的从头生物合成-文献精读108

Complete pathway elucidation of echinacoside in Cistanche tubulosa and de novo biosynthesis of phenylethanoid glycosides 管花肉苁蓉中松果菊苷全生物合成途径解析及苯乙醇苷类化合物的从头生物合成 摘要 松果菊苷&#xff08;ECH&#xff09;是最具代表性的苯乙醇苷…...

【C++】设计模式详解:单例模式

文章目录 Ⅰ. 设计一个类&#xff0c;不允许被拷贝Ⅱ. 请设计一个类&#xff0c;只能在堆上创建对象Ⅲ. 请设计一个类&#xff0c;只能在栈上创建对象Ⅳ. 请设计一个类&#xff0c;不能被继承Ⅴ. 请设计一个类&#xff0c;只能创建一个对象&#xff08;单例模式&#xff09;&am…...

CAN总线数据采集与分析

CAN总线数据采集与分析 目录 CAN总线数据采集与分析1. 引言2. 数据采集2.1 数据采集简介2.2 数据采集实现3. 数据分析3.1 数据分析简介3.2 数据分析实现4. 数据可视化4.1 数据可视化简介4.2 数据可视化实现5. 案例说明5.1 案例1:数据采集实现5.2 案例2:数据分析实现5.3 案例3…...

解决vsocde ssh远程连接同一ip,不同端口情况下,无法区分的问题

一般服务器会通过镜像分身或者容器的方式&#xff0c;一个ip分出多个端口给多人使用&#xff0c;但如果碰到需要连接同一user&#xff0c;同一个ip,不同端口的情况&#xff0c;vscode就无法识别&#xff0c;如下图所示&#xff0c;vscode无法区分该ip下不同端口的连接&#xff…...

AJAX案例——图片上传个人信息操作

黑马程序员视频地址&#xff1a; AJAX-Day02-11.图片上传https://www.bilibili.com/video/BV1MN411y7pw?vd_source0a2d366696f87e241adc64419bf12cab&spm_id_from333.788.videopod.episodes&p26 图片上传 <!-- 文件选择元素 --><input type"file"…...

团体程序设计天梯赛-练习集——L1-029 是不是太胖了

前言 5分级别里面目前做到的最难的一道题&#xff0c;但是非常简单&#xff0c;5分的题看看写点代码就行了。 L1-029 是不是太胖了 据说一个人的标准体重应该是其身高&#xff08;单位&#xff1a;厘米&#xff09;减去100、再乘以0.9所得到的公斤数。已知市斤的数值是公斤数…...

ubuntu20.04.6下运行VLC-Qt例子simple-player

下载examples-master.zip&#xff08;https://github.com/vlc-qt/examples&#xff09;&#xff0c;编译运行simple-player 参考链接&#xff1a; https://blog.csdn.net/szn1316159505/article/details/143743735 本文运行环境 Qt 5.15.2 Qt creator 5.0.2 主要步骤&#xf…...

LabVIEW温度修正部件测试系统

LabVIEW温度修正部件测试系统 这个基于LabVIEW的温度修正部件测试系统旨在解决飞行器温度测量及修正电路的测试需求。该系统的意义在于提供一个可靠的测试平台&#xff0c;用于评估温度修正部件在实际飞行器环境中的性能表现&#xff0c;从而确保飞行器的安全性和可靠性。 系统…...

细说机器学习算法之ROC曲线用于模型评估

系列文章目录 第一章&#xff1a;Pyhton机器学习算法之KNN 第二章&#xff1a;Pyhton机器学习算法之K—Means 第三章&#xff1a;Pyhton机器学习算法之随机森林 第四章&#xff1a;Pyhton机器学习算法之线性回归 第五章&#xff1a;Pyhton机器学习算法之有监督学习与无监督…...

Python3 【装饰器】项目实战:5个新颖的学习案例

Python3 【装饰器】项目实战&#xff1a;5个新颖的学习案例 以下是 5 个使用 Python 装饰器的综合应用项目&#xff0c;这些项目具有新颖性、前瞻性和实用性。每个项目都包含完整的代码、解释说明、测试案例和执行结果。 项目 1&#xff1a;API 请求限流器 描述&#xff1a;实…...

【深度学习】 UNet详解

UNet 是一种经典的卷积神经网络&#xff08;Convolutional Neural Network, CNN&#xff09;架构&#xff0c;专为生物医学图像分割任务设计。该模型于 2015 年由 Olaf Ronneberger 等人在论文《U-Net: Convolutional Networks for Biomedical Image Segmentation》中首次提出&…...

DeepSeek本地部署(windows)

一、下载并安装Ollama 1.下载Ollama Ollama官网:Ollama 点击"Download",会跳转至下载页面。 点击"Download for Windows"。会跳转Github进行下载,如下载速度过慢,可在浏览器安装GitHub加速插件。 2.安装Ollama 双击下载的安装文件,点击"Inst…...

简要介绍C语言/C++的三目运算符

三元运算符是C语言和C中的一种简洁的条件运算符&#xff0c;它的形式为&#xff1a; 条件表达式 ? 表达式1 : 表达式2; 三元运算符的含义 条件表达式&#xff1a;这是一个布尔表达式&#xff0c;通常是一个比较操作&#xff08;如 >、<、 等&#xff09;。 表达式1&am…...

SpringCloud系列教程:微服务的未来(十九)请求限流、线程隔离、Fallback、服务熔断

前言 前言 在现代微服务架构中&#xff0c;系统的高可用性和稳定性至关重要。为了解决系统在高并发请求或服务不可用时出现的性能瓶颈或故障&#xff0c;常常需要使用一些技术手段来保证服务的平稳运行。请求限流、线程隔离、Fallback 和服务熔断是微服务中常用的四种策略&…...

STM32 对射式红外传感器配置

这次用的是STM32F103的开发板&#xff08;这里面的exti.c文件没有how to use this driver 配置说明&#xff09; 对射式红外传感器 由一个红外发光二极管和NPN光电三极管组成&#xff0c;M3固定安装孔&#xff0c;有输出状态指示灯&#xff0c;输出高电平灯灭&#xff0c;输出…...

(动态规划路径基础 最小路径和)leetcode 64

视频教程 1.初始化dp数组&#xff0c;初始化边界 2、从[1行到n-1行][1列到m-1列]依次赋值 #include<vector> #include<algorithm> #include <iostream>using namespace std; int main() {vector<vector<int>> grid { {1,3,1},{1,5,1},{4,2,1}…...

嵌入式C语言:什么是共用体?

在嵌入式C语言编程中&#xff0c;共用体&#xff08;Union&#xff09;是一种特殊的数据结构&#xff0c;它允许在相同的内存位置存储不同类型的数据。意味着共用体中的所有成员共享同一块内存区域&#xff0c;因此&#xff0c;在任何给定时间&#xff0c;共用体只能有效地存储…...

QT简单实现验证码(字符)

0&#xff09; 运行结果 1&#xff09; 生成随机字符串 Qt主要通过QRandomGenerator类来生成随机数。在此之前的版本中&#xff0c;qrand()函数也常被使用&#xff0c;但从Qt 5.10起&#xff0c;推荐使用更现代化的QRandomGenerator类。 在头文件添加void generateRandomNumb…...

【4Day创客实践入门教程】Day2 探秘微控制器——单片机与MicroPython初步

Day2 探秘微控制器——单片机与MicroPython初步 目录 Day2 探秘微控制器——单片机与MicroPython初步MicroPython语言基础开始基础语法注释与输出变量模块与函数 单片机基础后记 Day0 创想启程——课程与项目预览Day1 工具箱构建——开发环境的构建Day2 探秘微控制器——单片机…...