Java反射(详细学习笔记)
Java反射
1. Java反射机制概述
Reflection(反射)是java被视为java动态语言的关键,反射机制允许程序在执行期间借助于Reflection API获取任何类的内部信息,并能直接操作任意对象的内部属性及方法。
Class c = Class.forName("java.lang.String");
加载完类之后,在堆内存的方法区中就会产生一个Class类型的对象(一个类只有一个Class对象),
这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。
-
正常方式:
引入包类
=>new实例化
=>获取实例对象
-
反射方式:
实例化对象
=>getClass()方法
=>获取完整包类名称
2. 理解Class类并获取Class实例
2.1Class类
- Class 本身就是一个类
- Class 对象只能由系统建立对象
- 一个加载的类在JVM中只有一个Class实例
- 一个Class对象对应的是一个加载到JVM中的一个.class文件
- 每个类的实例都会记得自己是由哪个Class实例所生成
- 通过Class可以完整地得到一个类中所有被加载的结构
- Class类是Reflection的根源,争对任何你想动态加载、运行的类,唯有先获得相应的Class对象。
2.2 Class类的常用方法
方法名 | 功能说明 |
---|---|
static ClassforName(String name) | 返回指定类名name的Calss对象 |
Object newInstance() | 调用缺省构造函数,返回Class对象的一个实例 |
getName() | 返回此Class对象所表示的实体(类,接口,数组类或void)的名称。 |
Class getSuperClass() | 返回当前Class对象的父类的Class对象返回当前类对象的父类的类对象 |
Class[] getinterfaces() | 获取当前Class对象的接口 |
ClassLoader getClassLoader() | 返回该类的类加载器 |
Constructor[] getConstructors() | 返回一个包含某些Constructor对象的数组 |
Method getMothed(String name,Class… T) | 返回一个Method对象,此对象的形参类型为paramType |
Field[] getDeclaredFields() | 返回Filed对象的一个数组 |
2.3 获取Class对象的方式
a.若已知具体的类对象,通过类的class属性获取,该方法最为安全可靠,程序性能高
Class c = Person.class;
b.已知某个类的实例,调用该实例的getClass()方法获取Class对象
Class c = person.getClass();
c.已知一个类的全类名,且该类在路径下,可通过Class类的静态方法forName()获取
可能抛出ClassNoFoundException
Class c = Class.forName("demo.Student");
d.内置基本数据类型可以直接用类名.Type
e.利用ClassLoader
2.4 哪些类型有Class对象
- class:外部类、成员(成员内部类、静态内部类),局部内部类、匿名内部类。
- interface:接口
- []:数组
- enum:枚举
- annotation:注解@interface
- primitive type:基本数据类型
- void
public static void main(String[] args) {Class c1 = Object.class;Class c2 = String[].class;Class c3 = int.class;Class c4 = Override.class;Class c5 = ElementType.class;Class c6 = Integer.class;Class c7 = void.class;Class c8 = Class.class;
}
3.类的加载与ClassLoader
3.1 Java内存
(1)堆
- 存放new的对象和数组
- 可以被所有的线程共享,不会存放别的对象引用
(2)栈
- 存放基本变量类型(会包含这个基本类型的具体数值)
- 引用对象的变量(会存放这个引用在堆里面的具体地址)
(3)方法区
- 可以被所有线程共享
- 包含了所有的class和static变量
3.2 类的加载过程
当程序主动使用某个类时,如果该类还没有被加载到内存中,则系统会通过如下三个步骤对类进行初始化。
类的加载(Load)=>类的链接(Link)=>类的初始化(initialize)
-
类的加载(Load)
将类的class文件读入内存,并为之建立一个java.lang.Class对象。此过程由类加载器完成。
-
类的链接(Link)验证>准备>解析
将Java类的二进制代码合并到JVM的运行状态之中的过程。
(1)验证:确保加载类的信息符合JVM规范,没有安全方面的问题。
(2)准备:正式为类变量(static)分配内存并设置类变量默认初始值的阶段,这些内存都将在方法中进行分配。
(3)解析:虚拟机常量池的符号引用(常量名)替换为直接引用(地址)的过程。
-
类的初始化(initialize)
JVM负责对类进行初始化。
(1)执行类构造器<clinit>()方法的过程。类构造器<clinit>()方法是由编译期自动收集类中所有类变量的赋值动作和静态代码块中的语句合并产生的。(类构造器是构造类信息的,不是构造该类对象的构造器)。
(2)当初始化一个类的时候,如果发现其父类还没有进行初始化,则需要先触发其父类的初始化。
(3)虚拟机会保证一个类的<clinit>()方法在多线程环境中被正确加锁和同步。
3.3 类的初始化
类的主动引用(一般发生类的初始化)
(1)当虚拟机启动,先初始化main方法所在的类
(2)new 一个对象的对象
(3)调用类的静态成员(除去final常量)和静态方法
(4)使用java.lang.reflect包(反射)
(5)当初始化一个类,如果其父类没有初始化,则先初始化他的父类。
类的被动引用(不会发生类的初始化)
(1)当访问一个静态域时,只有真正声明这个域的类才会初始化。如:当通过子类引用父类的静态变量,不会导致子类初始化。
(2)通过数组定义的类引用,不会触发此类的初始化。
(3)引用常量不会触发此类的初始化(常量在链接阶段就存入调用类的常量池中了)
class Father {static int a = 2;static {System.out.println("父类被初始化");}
}class Son extends Father {static {System.out.println("子类被初始化");m = 300;}static int m = 100;static final int M = 1;
}public class Test6 {static {System.out.println("Main类被加载");}public static void main(String[] args) throws ClassNotFoundException {//主动引用//Son son = new Son();//反射也会产生主动引用// Class.forName("org.example.reflection.Son");///** 主动引用结果* Main类被加载* 父类被初始化* 子类被初始化*/// 不会产生类的引用方法// System.out.println(Son.a);/** 以上结果* Main类被加载* 父类被初始化* 2*/// 数组//Son[] ar = new Son[10];/** 以上结果* Main类被加载*/}
}
3.4 类加载器的作用
**类加载的作用:**将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后在堆中生成一个代表这个类的java.lang.Class对象,作为方法区中类数据的访问入口。
**类缓存:**标准的JavaSE类加载器可以按要求查找类,但一旦某个类被加载到类加载器中,它将维持加载(缓存)一段时间。不过JVM垃圾回收机制可以回收这些Class对象。
类加载器作用是用来把类(class)装载进内存的。JVM规范了定义了如下类型的类的加载器。
自定义类加载器
>System Classloader(系统类加载器)
>Extecnsion Classloader(扩展类加载器)
>Bootstap Classloader(引导类加载器)
- 自低向上检查类是否已经被装载
- 自顶向下尝试加载类
(1)引导类加载器
引导类加载器:用C++编写的,是JVM自带的类加载器,负责Java平台核心库,用来装载核心类库。该加载器无法直接获取。
(2)扩展类加载器
扩展类加载器:负责jre/lib/ext目录下的jar包或-D java.ext.dirs指定目录下的jar包装入工作库。
(3)系统类加载器:负责java -classpath或-Djava.class.path所指的目录下的类与jar包装入工作,是最常用的加载器
public static void main(String[] args) throws ClassNotFoundException {// 获取系统类的加载器ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();System.out.println("系统类的加载器 " + systemClassLoader);// 获取系统类的加载器的父类加载器->扩展类加载器ClassLoader parent = systemClassLoader.getParent();System.out.println("扩展类加载器 " + parent);// 获取系扩展类加载器的父类加载器->根加载器(c/c++)ClassLoader parent1 = parent.getParent();System.out.println("根加载器 " + parent1);// 测试当前类是哪个加载器加载的ClassLoader classLoader = Class.forName("org.example.reflection.Test7").getClassLoader();System.out.println("org.example.reflection.Test7 " + classLoader);// 测试JDK内部类是谁加载的ClassLoader classLoader1 = Class.forName("java.lang.Object").getClassLoader();System.out.println("java.lang.Object " + classLoader1);// 获取系统类加载器可以加载的路径String property = System.getProperty("java.class.path");String[] split = property.split(";");System.out.println(Arrays.toString(split));
}
系统类的加载器 sun.misc.Launcher$AppClassLoader@18b4aac2
扩展类加载器 sun.misc.Launcher$ExtClassLoader@1b6d3586
根加载器 null
org.example.reflection.Test7 sun.misc.Launcher$AppClassLoader@18b4aac2
java.lang.Object null
[E:\Java\jdk1.8.0_191\jre\lib\charsets.jar, E:\Java\jdk1.8.0_191\jre\lib\deploy.jar, E:\Java\jdk1.8.0_191\jre\lib\ext\access-bridge-64.jar, E:\Java\jdk1.8.0_191\jre\lib\ext\cldrdata.jar, E:\Java\jdk1.8.0_191\jre\lib\ext\dnsns.jar, E:\Java\jdk1.8.0_191\jre\lib\ext\jaccess.jar, E:\Java\jdk1.8.0_191\jre\lib\ext\jfxrt.jar, E:\Java\jdk1.8.0_191\jre\lib\ext\localedata.jar, E:\Java\jdk1.8.0_191\jre\lib\ext\nashorn.jar, E:\Java\jdk1.8.0_191\jre\lib\ext\sunec.jar, E:\Java\jdk1.8.0_191\jre\lib\ext\sunjce_provider.jar, E:\Java\jdk1.8.0_191\jre\lib\ext\sunmscapi.jar, E:\Java\jdk1.8.0_191\jre\lib\ext\sunpkcs11.jar, E:\Java\jdk1.8.0_191\jre\lib\ext\zipfs.jar, E:\Java\jdk1.8.0_191\jre\lib\javaws.jar, E:\Java\jdk1.8.0_191\jre\lib\jce.jar, E:\Java\jdk1.8.0_191\jre\lib\jfr.jar, E:\Java\jdk1.8.0_191\jre\lib\jfxswt.jar, E:\Java\jdk1.8.0_191\jre\lib\jsse.jar, E:\Java\jdk1.8.0_191\jre\lib\management-agent.jar, E:\Java\jdk1.8.0_191\jre\lib\plugin.jar, E:\Java\jdk1.8.0_191\jre\lib\resources.jar, E:\Java\jdk1.8.0_191\jre\lib\rt.jar, E:\IdeaProjects\java-demo-parent\basics\target\classes, E:\Program Files\JetBrains\IntelliJ IDEA 2022.3.2\lib\idea_rt.jar]
4.创建运行时类对象
public class User {private String name;private int id; }
// 获得Class对象
Class c1 = Class.forName("org.example.reflection.User");
(1)调用无参构造器
// 构建一个对象(调用无参构造器)
User user1 = (User) c1.newInstance();
System.out.println("user1 " + user1);
user1 User{name=‘null’, id=0}
(2)调用有参数构造器
// 通过构造器创建对象
Constructor constructor = c1.getDeclaredConstructor(String.class, int.class);
User user2 = (User) constructor.newInstance("张三", 1);
System.out.println("user2 " + user2);
user2 User{name=‘张三’, id=1}
(3)通过反射调用方法
// 通过反射调用方法
User user3 = (User) c1.newInstance();
// 通过反射获取一个方法
Method setName = c1.getDeclaredMethod("setName", String.class);
setName.invoke(user3, "李四");
System.out.println("user3 " + user3);
(1)
public Object invoke(Object obj, Object... args)
- Object对应原方法的返回值,若原方法无返回值,此时返回null
- 若原方法为静态方法,此时形参Object obj可为null
- 若原方法形参列表为空,则Object[] args为null
- 若原方法声明为private,则需要在调用此invoke()方法前,显式调用方法对象的setAccessible(true)方法,将可访问private的方法。
(2)
setAccessible(true)
启动和禁用访问安全检查的开关
- Method、Field、Constructor对象都有setAccessible()
- 取消检查、提高反射效率
(4)通过反射操作属性
// 通过反射操作属性
User user4 = (User) c1.newInstance();
Field name = c1.getDeclaredField("name");
// 无法操作私有属性,关闭安全检测setAccessible(true)
name.setAccessible(true);
name.set(user4, "王二");
如果没有设置会报异常
IllegalAccessException
:User with modifiers "private"
5.获取运行时类的完整结构
public class User {private String name;private int id; }
通过反射获取运行时类的完整结构
Filed(字段)、Method(方法)、Constructor(构造)、Superclass(父类)、Interface(接口)、Annotation(注解)
// 通过包名获取
Class c1 = Class.forName("org.example.reflection.User");
// 通过对象获取
//User user = new User();
//Class c2 = user.getClass();
// 获取类的名字
System.out.println("包名+类名 " + c1.getName());
System.out.println("类名 " + c1.getSimpleName());
// 获取对象属性
System.out.println("=============对象属性=============");
// getFields() 只能找到public属性
Field[] fields = c1.getDeclaredFields();
for (Field field : fields) {System.out.println(field);
}
// 获取指定的属性
System.out.println("获取指定的属性" + c1.getDeclaredField("id"));
// 获取类的方法
// getMethods:获取本类及父类的全部public方法
System.out.println("=============类的方法=============");
Method[] methods = c1.getMethods();
for (Method method : methods) {System.out.println(method);
}
// 获取本类的所有方法
System.out.println("=========getDeclaredMethods=========");
Method[] methods1 = c1.getDeclaredMethods();
for (Method method : methods1) {System.out.println(method);
}
// 获取指定的方法
System.out.println("指定方法" + c1.getDeclaredMethod("getName", null));
System.out.println("指定方法" + c1.getDeclaredMethod("setName", String.class));// 获取指定构造器
System.out.println("=============指定构造器=============");
Constructor[] constructors = c1.getDeclaredConstructors();
for (Constructor c : constructors) {System.out.println(c);
}
System.out.println("获取指定构造器 " + c1.getDeclaredConstructor(String.class, int.class));
包名+类名 org.example.reflection.User
类名 User
//对象属性
private java.lang.String org.example.reflection.User.name
private int org.example.reflection.User.id
获取指定的属性private int org.example.reflection.User.id
//类的方法
public java.lang.String org.example.reflection.User.toString()
public java.lang.String org.example.reflection.User.getName()
public int org.example.reflection.User.getId()
public void org.example.reflection.User.setName(java.lang.String)
public void org.example.reflection.User.setId(int)
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
//getDeclaredMethods
public java.lang.String org.example.reflection.User.toString()
public java.lang.String org.example.reflection.User.getName()
public int org.example.reflection.User.getId()
public void org.example.reflection.User.setName(java.lang.String)
public void org.example.reflection.User.setId(int)
指定方法public java.lang.String org.example.reflection.User.getName()
指定方法public void org.example.reflection.User.setName(java.lang.String)
//指定构造器
public org.example.reflection.User(java.lang.String,int)
public org.example.reflection.User()
获取指定构造器 public org.example.reflection.User(java.lang.String,int)
6.获取泛型
Java采用泛型擦除的机制来引入泛型,Java中的泛型仅仅是给编译器javac使用的,确保数据安全性和免去强制类型转换问题,但是,一旦编译完成,所有和泛型有关的类型全部擦除。
为了通过反射操作这些类型,Java新增了ParameterizedType
,GenericArrayType
,
TypeVariable和WildcardType几种类型来代表不能被归一到Class类中的类型但是又和原始类型齐名的类型.
ParameterizedType
:表示一种参数化类型,比如Collection<String>
GenericArrayType
:表示一种元素类型是参数化类型或者类型变量的数组类型
TypeVariable
:是各种类型变量的公共父接口
WildcardType
:代表一种通配符类型表达式
public class Test11 {public void test01(Map<String, User> map, List<User> list) {System.out.println("test01");}public Map<String, User> test02() {System.out.println("test02");return null;}public static void main(String[] args) throws NoSuchMethodException {// 参数泛型System.out.println("===========参数泛型==========");Method test01 = Test11.class.getMethod("test01", Map.class, List.class);Type[] genericExceptionTypes = test01.getGenericParameterTypes();for (Type t : genericExceptionTypes) {System.out.println("genericExceptionTypes " + t);if (t instanceof ParameterizedType) {Type[] actualTypeArguments = ((ParameterizedType) t).getActualTypeArguments();for (Type i : actualTypeArguments) {System.out.println("actualTypeArguments " + i);}}}// 返回值泛型System.out.println("===========返回值泛型==========");Method test02 = Test11.class.getMethod("test02");Type genericReturnType = test02.getGenericReturnType();System.out.println("genericReturnType " + genericReturnType);if (genericReturnType instanceof ParameterizedType) {Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();for (Type i : actualTypeArguments) {System.out.println("actualTypeArguments " + i);}}}
}
//参数泛型
genericExceptionTypes java.util.Map<java.lang.String, org.example.reflection.User>
actualTypeArguments class java.lang.String
actualTypeArguments class org.example.reflection.User
genericExceptionTypes java.util.List<org.example.reflection.User>
actualTypeArguments class org.example.reflection.User
//返回值泛型
genericReturnType java.util.Map<java.lang.String, org.example.reflection.User>
actualTypeArguments class java.lang.String
actualTypeArguments class org.example.reflection.User
7.反射操作注解
@TableName("db_student")
class Student {@Column(name = "s_id", type = "int", length = 10)private int id;@Column(name = "s_name", type = "varchar", length = 32)private String name;public Student() {}public Student(int id, String name) {this.id = id;this.name = name;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "Student{" +"id=" + id +", name='" + name + '\'' +'}';}
}/*** 表名*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TableName {String value();
}@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Column {String name();String type();int length();
}public class Test12 {public static void main(String[] args) {Student student = new Student();TableName annotation = student.getClass().getAnnotation(TableName.class);System.out.println("类注解值:" + annotation.value());Field[] declaredFields = student.getClass().getDeclaredFields();for (Field field : declaredFields) {Column a = field.getAnnotation(Column.class);System.out.println("====属性:" + field.getName() + "====");System.out.println("名称:" + a.name() + ",类型:" + a.type() + ",长度:" + a.length());}}}
类注解值:db_student
//属性:id
名称:s_id,类型:int,长度:10
//属性:name
名称:s_name,类型:varchar,长度:32
相关文章:

Java反射(详细学习笔记)
Java反射 1. Java反射机制概述 Reflection(反射)是java被视为java动态语言的关键,反射机制允许程序在执行期间借助于Reflection API获取任何类的内部信息,并能直接操作任意对象的内部属性及方法。 Class c Class.forName(&quo…...

学习 Python 之 Pygame 开发魂斗罗(十二)
学习 Python 之 Pygame 开发魂斗罗(十二)继续编写魂斗罗1. 修改玩家扣减生命值2. 解决玩家下蹲子弹不会击中玩家而是直接让玩家死亡的问题3. 完善地图4. 增加产生敌人函数,解决一直产生敌人的问题5. 给玩家类增加计算玩家中心的方法继续编写魂…...

Linux下字符设备驱动开发以及流程介绍
文章目录1 - 字符设备介绍2 - 字符设备开发流程图3 - 字符设备开发流程具体讲解(1)设备编号的定义与申请【1】Linux主次设备号介绍【2】分配设备编号【3】释放主次设备号(2)定义file_operations结构体-初始化接口函数(…...

Web自动化框架断言方法实现
前言1、设计用例方法关键字1.1、获取元素属性值2.1、断言2、代码实现2.1、实现获取元素属性值2.1.1 函数实现2.1.2 方法配置2.1.2 用例调试2.1.3 html属性2.2、实现断言2.2.1 函数2.2.2 方法配置2.2.3 用例调试1)断言结果成功2)断言结果失败前言 本文的…...

8大核心语句,带你深入python
人生苦短 我用python 又来给大家整点好东西啦~ 咱就直接开练噜!内含大量代码配合讲解 python 安装包资料:点击此处跳转文末名片获取 1. for - else 什么?不是 if 和 else 才是原配吗? No,你可能不知道, else 是个…...

【批处理】- 批处理自动安装Mysql与Redis
前言 在全新环境中安装MySQL与Redis操作是挺麻烦的,于是就想使用脚本来自动安装,使用批处理进行一步到位的安装,后面还能使用工具进行打包成exe可执行文件,一键安装,最后能够更好的部署项目到windows系统的服务器。 …...

聊聊华为的工作模式
目录 一、试用期与加班工资 二、招聘 三、月度答辩和转正答辩 四、可信考试认证 五、接口人 六、问题缺陷单 七、代码检视 八、功能开发 九、出征海外 一、试用期与加班工资 一般而言,试用期持续的时间为3-6个月,工资、奖金都按正式员工的标准…...

燕山大学-面向对象程序设计实验-实验6 派生与继承:多重派生-实验报告
CSDN的各位友友们你们好,今天千泽为大家带来的是燕山大学-面向对象程序设计实验-实验5 派生与继承:单重派生-实验报告,接下来让我们一起进入c的神奇小世界吧,相信看完你也能写出自己的 实验报告!本系列文章收录在专栏 燕山大学面向对象设计报告中 ,您可以在专栏中找…...

分割两个字符串得到回文串[抽象--去除具体个性取共性需求]
抽象前言一、分割两个字符串得到回文串二、双指针总结参考文献前言 抽象去个性留共性,是因为具体个性对于解决问题是个累赘。少了累赘,直击需求,才能进行问题转换或者逻辑转换。 一、分割两个字符串得到回文串 二、双指针 // 限定死了&…...

【LeetCode】1609. 奇偶树、1122. 数组的相对排序
作者:小卢 专栏:《Leetcode》 喜欢的话:世间因为少年的挺身而出,而更加瑰丽。 ——《人民日报》 1609. 奇偶树 1609. 奇偶树 题目描述: 如果一棵二叉树满足下述几个条件&#x…...

【C++初阶】4. Date类的实现
如果下面博客有不理解的地方,可以查看源码:代码提交:日期类的实现 1. 构造函数的实现 由于系统实现的默认构造函数即便采用默认值的形式也只能存在1个固定的默认日期(例如:1997-1-1)。所以,构…...

ES6新特性--变量声明
可以使用let关键字来声明变量let a;let b,c;//同时声明多个变量let stu = 张三;let name =李四,age = 12;//声明变量的同时赋值 let关键字使用的注意事项(1).变量在声明的时候不可以重复,这也符合其他语言的变量声明规范 let name = 李四; let name = 张三;//这里开始报错,但…...

【Django】缓存机制
文章目录缓存的介绍Django的6种缓存方式开发调试缓存dummy.DummyCache内存缓存locmem.LocMemCache文件缓存filebased.FileBasedCache⭐️数据库缓存db.DatabaseCacheMemcache缓存memcached.MemcachedCacheMemcache缓存memcached.PyLibMCCacheDjango缓存的应用内存缓存cache_pag…...

我的创作纪念日——一年的时间可以改变很多
机缘 不知不觉来到CSDN已经创作一年了。打心底讲,对于在CSDN开始坚持创作的原因,我用一句话来概括最合适不过了——“无心插柳柳成荫” 为什么这么说呢? 这要从我的一篇博客说起——《输入命令Javac报错详解》: 那也是我第一次…...

Jetson Nano驱动机器人的左右两路电机
基于Jetson Nano板子搭建一个无人车,少不了减速电机驱动轮子滚动,那如何驱动呢?从Jetson.GPIO库文件来说,里面没有支持产生PWM的引脚,也就意味着Jetson nano没有硬件产生PWM的能力,所以我们不得不使用别的方…...

如何通过openssl生成公钥和私钥?
1、生成RSA秘钥的方法 生成RSA秘钥的方法: openssl genrsa -des3 -out privkey.pem 2048 注:建议用2048位秘钥,少于此可能会不安全或很快将不安全。 这个命令会生成一个2048位的秘钥,同时有一个des3方法加密的密码,…...

Verilog的If语句和Case语句
这篇文章将讨论 verilog 中两个最常用的结构----if语句和case语句。在之前的文章中学习了如何使用过程块(例如always块)来编写按顺序执行的verilog 代码。此外还可以在过程块中使用许多语句----统称为顺序语句,如case 语句和 if 语句。这篇文…...

HJ31 单词倒排
描述 对字符串中的所有单词进行倒排。 说明: 1、构成单词的字符只有26个大写或小写英文字母; 2、非构成单词的字符均视为单词间隔符; 3、要求倒排后的单词间隔符以一个空格表示;如果原字符串中相邻单词间有多个间隔符时…...

leetcode——203.移除链表元素
文章目录🐨1.题目🪅2.解法1-头节点迭代🌿2.1 思路🌿2.2 代码实现🦆3. 解法2-创建新链表🎏3.1 思路🎏3.2 代码实现🐐4. 题目链接🐨1.题目 给你一个链表的头节点head和一个…...

GPT-4来袭:开启人工智能新时代
文章目录介绍GPT4 模型演示示例示例 1示例 2示例 3示例 4示例 5最后Reference介绍 2023年3月15日,OpenAI公司正式发布了先进的自然语言处理模型GPT-4,前不久发布的GPT-3.5模型只能理解文字的语言模型,而新发布的GPT4则是多模态模型ÿ…...

芯微电子IPO终止:业绩开始大幅下滑,王日新、王苟新兄弟不同命
近日,深圳证券交易所披露的信息显示,黄山芯微电子股份有限公司(下称“芯微电子”)申请撤回发行上市申请文件。因此,深圳证券交易所决定终止对其首次公开发行股票并在创业板上市的审核。 据贝多财经了解,芯…...

【C++】用手搓的红黑树手搓set和map
目录 一、set/map的底层结构 1、set/map的源码 2、利用模板区分set/map 3、利用仿函数控制比较大小 二、set/map的迭代器(红黑树的迭代器) 1、红黑树的begin、end迭代器 2、红黑树迭代器的operator 3、红黑树迭代器的operator-- 三、set的const…...

【C++】空指针弃NULL用nullptr
空指针(null pointer)不指向任何对象,在试图使用一个指针之前代码可以首先检查它是否为空。声明空指针的3种方法: int* p1 NULL; int* p2 nullptr; int* p3 0; 在C语言中常用NULL生成空指针,NULL是一个宏…...

【selenium学习】数据驱动测试
数据驱动在 unittest 中,使用读取数据文件来实现参数化可以吗?当然可以。这里以读取 CSV文件为例。创建一个 baidu_data.csv 文件,如图所示:文件第一列为测试用例名称,第二例为搜索的关键字。接下来创建 test_baidu_da…...

嵌入式硬件电路设计的基本技巧
目录 1 分模块 2 标注关键参数 3 电阻/电容/电感/磁珠的注释 4 可维修性 5 BOM表归一化 6 电源和地的符号 7 测试点 8 网络标号 9 容错性/兼容性 10 NC、NF 11 版本变更 12 悬空引脚 13 可扩展性 14 防呆 15 信号的流向 16 PCB走线建议 17 不使用\表示取反 不…...

Spring MVC 图片的上传和下载
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...

远程工具神器之MobaXterm (小白必看)
目录 1、介绍 2、ssh连接详解过程 3、特点 1、介绍 带有 X11 服务器、选项卡式 SSH 客户端、网络工具等的 Windows 增强型终端。 MobaXterm 是您远程计算的终极工具箱。在单个Windows应用程序中,它提供了大量功能,这些功能是为程序员,网站管…...

VRIK+Unity XR Interaction Toolkit 实现VR上半身的追踪(附带VRM模型导入Unity方法和手腕扭曲的解决方法)
文章目录📕第一步:配置 OpenXR XR Interaction Toolkit 的开发环境📕第二步:导入人物模型⭐VRM 模型导入 Unity 的方法📕第三步:配置 VRIK⭐给模型加上 VRIK 组件⭐将模型的头部和手部的位置作为 VR 追踪目…...

【C++进阶】map的介绍和使用
文章目录map的介绍map的模板参数介绍map的容器介绍map重要容器接口的介绍及使用构造函数增删查改迭代器的使用map的介绍 map是关联容器,它按照特定的次序(按照key来比较)存储由键值key和值value组合而成的元素。在map中,键值key通常用于排序和惟一地标识…...

第十四届蓝桥杯三月真题刷题训练——第 15 天
目录 第 1 题:斐波那契与7 问题描述 答案提交 运行限制 代码: 第 2 题:小蓝做实验 问题描述 答案提交 运行限制 代码: 第 1 题:斐波那契与7 问题描述 斐波那契数列的递推公式为: FnFn−1Fn−2, 其中 F1F21…...