微网站 pc端网站开发/百度交易平台
文章目录
- 一、泛型介绍
- 1. 背景
- 2. 概念
- 3. 好处
- 二、泛型声明
- 泛型类型符号
- 泛型声明方式
- 三、类型擦除
- 1. 什么是类型擦除
- 桥接方法
- 2. 为何需要类型擦除
- 3. 类型信息并未完全擦除
- 四、泛型使用
- 1. 泛型类
- 2. 泛型接口
- 3. 泛型方法
- 五、泛型扩展
- 1. 泛型的上下边界
- 泛型的上边界
- 泛型的下边界
- 2. 泛型中使用&(并且)操作符
一、泛型介绍
1. 背景
在JDK5之前,还没有泛型。在使用集合时,需要构建一个元素类型为Object的集合,集合能够存储任意的数据类型对象,在使用该集合的过程中,需要明确知道存储每个元素的数据类型,否则很容易引发ClassCastException异常。
2. 概念
JDK5中引入Java泛型这个新特性,泛型提供了编译时类型安全监测机制,该机制允许我们在编译时检测到非法的类型数据结构。
- 泛型主要是方便了程序员的代码编写,以及更好的安全性检测。
- 泛型是一种运用于编译时期的技术,泛型的出现,实现了把运行阶段的错误提前暴露到了编译阶段。
在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
参数化类型
泛型的本质就是参数化类型。在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型。
参数化类型,顾名思义就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。
简单理解:泛型就是把类型当作是参数一样进行传递,数据类型只能是引用类型。
3. 好处
- 编译时类型安全监测
- 消除强制类型转换
二、泛型声明
泛型的使用需要先声明,声明通过<符号>的方式,符号可以任意,编译器通过识别尖括号和尖括号内的字母来解析泛型。
- 泛型的类型只能为引用类型,不能为基本类型
- 尖括号的位置也是固定的,只能在类名之后或方法返回值之前
泛型类型符号
一般约定的类型符号:
- E:Element (表示集合元素,在集合中使用)
- T:Type(表示Java类)
- K:Key(表示键,比如Map中的key)
- V:Value(表示值,比如Map中的key)
- N:Number(表示数值类型)
- ?:泛型通配符(表示不确定的Java类型)
泛型声明方式
常见声明方式:
- <T>:普通声明
- <?>:无边界声明
- <? extends 类>:上边界声明
- <? super 类>:下边界声明
需要注意:通配符?不能在泛型类(接口)的声明上使用。
三、类型擦除
1. 什么是类型擦除
Java的泛型是伪泛型,这是因为Java在编译期间,所有的泛型信息都会被擦掉,正确理解泛型概念的首要前提是理解类型擦除。
官方描述:
泛型被引入Java语言,以在编译时提供更严格的类型检查,并支持泛型编程。
为了实现泛型,Java编译器将类型擦除应用于:
- 如果类型参数是无界的,则将泛型类型中的所有类型参数替换为其边界或Object。因此,生成的字节码只包含普通类、接口和方法。
- 如果需要,请插入类型强制转换以保持类型安全。
- 生成桥接方法以保留扩展泛型类型中的多态性。
类型擦除确保了不会为参数化类型创建新类;所以泛型是没有运行时开销的。
对官方描述的理解:
- 泛型的使用,使得编译器在编译时进行了更严格类型检查,避免运行时引发ClassCastException异常
- 泛型应用于编译阶段,用泛型定义的类型参数,会在编译时会去掉,这称之为“类型擦除”。编译后生成的字节码class文件不包含泛型类型信息,运行时虚拟机并不知道泛型。
- 编译时,泛型的类型参数会被替换为其边界或Object
- 编译时,使用泛型的地方会插入强制类型转换
- 在泛型父类、泛型接口的场景中,会生成桥接方法以保留泛型类型中的多态性。
- 编译时,如果子类复写的父类中的方法使用了泛型类型,子类会自动生成一个该方法的桥接方法
- 编译时,如果实现类实现接的接口方法使用了泛型类型,实现类会自动生成一个该方法的桥接方法
public class Test {public static void main(String[] args) {ArrayList<Integer> list1 = new ArrayList<>();ArrayList<Integer> list2 = new ArrayList<>();System.out.println(list1.getClass() == list2.getClass());}
}
打印结果为true,因为list1和list2的Class对象是同一个Class。
特别注意:对于编译后生成的字节码class文件不包含泛型类型信息这句话,网上普遍都说这个说法,但都没去仔细解释,理解的时候可能会有不解,因为你发现现实中的class文件中时是包含了泛型类型信息的。下文会解释这个问题。
桥接方法
桥接方法是JDK1.5引入泛型后,为使java泛型方法生成的字节码与JDK1.5版本之前的字节码兼容由编译器自动生成的。
子类继承父类(实现接口)实现泛型方法的情况,父类经过编译后方法的泛型类型入参和返回值类型都为Object(或上边界类型),而子类的实现方法的入参和返回值类型为具体的泛型类型(如String),此时子类并没有重写父类的方法了(返回值和形参与父类完全相同才是重写方法),所以需要编译器生成一个桥接方法达到重写父类方法的目的。
因此当子类继承父类(实现接口)实现泛型方法的时候,编译器会为子类自动生成桥接方法。
举例说明:
public interface TestInterface<T> {T get();void set(T t);
}class Test3 implements TestInterface<Integer> {@Overridepublic Integer get() {return null;}@Overridepublic void set(Integer s) {}
}
class MainClass {public static void main(String[] args) {Method[] methods = Test3.class.getDeclaredMethods();for (Method method : methods) {System.out.println((method.isBridge() ? "桥接方法:" : "普通方法:") + method.toGenericString());}}
}
打印结果:
桥接方法:public java.lang.Object com.joker.test.generic.Test3.get()
普通方法:public java.lang.Integer com.joker.test.generic.Test3.get()
桥接方法:public void com.joker.test.generic.Test3.set(java.lang.Object)
普通方法:public void com.joker.test.generic.Test3.set(java.lang.Integer)
以set方法作分析:
- 编译时,经过类型擦除后,TestInterface接的set方法变成了void set(Object t)
- 而实现类Test3原本的实现方法是void set(Integer s),明显已经不再是实现方法了
- 为了解决这个问题,Java编译器通过桥接的生成了一个**void set(Object t)**方法,保证了实现方法
2. 为何需要类型擦除
为什么Java不像C#一样实现真正的泛型呢?而要用类型擦除的方式实现了个伪泛型。
其实JDK1.5引入的泛型采用类型擦除式实现的根本原因是兼容性上的取舍,而不是因为实现不了真正意义上的泛型。
为了确保JDK1.5之前的和JDK1.5能使用同一个类加载器,所以Java通过类型擦除的方式实现的泛型支持。经过编译阶段的泛型类型擦除后,与JDK1.5之前是基本没有变动。
3. 类型信息并未完全擦除
下面举例说明:
定义一个Demo泛型类和一个Test测试类。
public class Demo<T> {private T id;public T getId() {return id;}
}
public class Test {public static void main(String[] args) {Demo<Integer> demo = new Demo<>();Integer id = demo.getId();}
}
1. 查看IDEA编译后的class文件
Demo.calss
public class Demo<T> {private T id;public Demo() {}public T getId() {return this.id;}
}
Test.class
public class Test {public Test() {}public static void main(String[] args) {Demo<Integer> demo = new Demo();Integer id = (Integer)demo.getId();}
}
从class文件可见:
- 使用泛型的地方进行了强制类型转换
- 但泛型的类型参数并未替换为Object
原因:在编译过程中,泛型信息是被擦除了,但是声明侧的泛型信息会被class文件以Signature的形式保留在Class文件的Constant pool中。
2. 使用javap命令反编译Demo.class文件和Test.class文件
javap -v Demo.class
Classfile /D:/work/my/springboot/target/classes/com/joker/test/generic/Demo.classLast modified 2023-2-14; size 610 bytesMD5 checksum 4851ec541c05f1d29bee93edb79085f0Compiled from "Demo.java"
public class com.joker.test.generic.Demo<T extends java.lang.Object> extends java.lang.Objectminor version: 0major version: 52flags: ACC_PUBLIC, ACC_SUPER
Constant pool:#1 = Methodref #4.#24 // java/lang/Object."<init>":()V#2 = Fieldref #3.#25 // com/joker/test/generic/Demo.id:Ljava/lang/Object;#3 = Class #26 // com/joker/test/generic/Demo#4 = Class #27 // java/lang/Object#5 = Utf8 id#6 = Utf8 Ljava/lang/Object;#7 = Utf8 Signature#8 = Utf8 TT;#9 = Utf8 <init>#10 = Utf8 ()V#11 = Utf8 Code#12 = Utf8 LineNumberTable#13 = Utf8 LocalVariableTable#14 = Utf8 this#15 = Utf8 Lcom/joker/test/generic/Demo;#16 = Utf8 LocalVariableTypeTable#17 = Utf8 Lcom/joker/test/generic/Demo<TT;>;#18 = Utf8 getId#19 = Utf8 ()Ljava/lang/Object;#20 = Utf8 ()TT;#21 = Utf8 <T:Ljava/lang/Object;>Ljava/lang/Object;#22 = Utf8 SourceFile#23 = Utf8 Demo.java#24 = NameAndType #9:#10 // "<init>":()V#25 = NameAndType #5:#6 // id:Ljava/lang/Object;#26 = Utf8 com/joker/test/generic/Demo#27 = Utf8 java/lang/Object
{public com.joker.test.generic.Demo();descriptor: ()Vflags: ACC_PUBLICCode:stack=1, locals=1, args_size=10: aload_01: invokespecial #1 // Method java/lang/Object."<init>":()V4: returnLineNumberTable:line 7: 0LocalVariableTable:Start Length Slot Name Signature0 5 0 this Lcom/joker/test/generic/Demo;LocalVariableTypeTable:Start Length Slot Name Signature0 5 0 this Lcom/joker/test/generic/Demo<TT;>;public T getId();descriptor: ()Ljava/lang/Object;flags: ACC_PUBLICCode:stack=1, locals=1, args_size=10: aload_01: getfield #2 // Field id:Ljava/lang/Object;4: areturnLineNumberTable:line 13: 0LocalVariableTable:Start Length Slot Name Signature0 5 0 this Lcom/joker/test/generic/Demo;LocalVariableTypeTable:Start Length Slot Name Signature0 5 0 this Lcom/joker/test/generic/Demo<TT;>;Signature: #20 // ()TT;
}
Signature: #21 // <T:Ljava/lang/Object;>Ljava/lang/Object;
SourceFile: "Demo.java"
javap -v Test.class
Classfile /D:/work/my/springboot/target/classes/com/joker/test/generic/Test.classLast modified 2023-2-14; size 739 bytesMD5 checksum a82bd374c2bff99147acd130f3819415Compiled from "Test.java"
public class com.joker.test.generic.Testminor version: 0major version: 52flags: ACC_PUBLIC, ACC_SUPER
Constant pool:#1 = Methodref #7.#28 // java/lang/Object."<init>":()V#2 = Class #29 // com/joker/test/generic/Demo#3 = Methodref #2.#28 // com/joker/test/generic/Demo."<init>":()V#4 = Methodref #2.#30 // com/joker/test/generic/Demo.getId:()Ljava/lang/Object;#5 = Class #31 // java/lang/Integer#6 = Class #32 // com/joker/test/generic/Test#7 = Class #33 // java/lang/Object#8 = Utf8 <init>#9 = Utf8 ()V#10 = Utf8 Code#11 = Utf8 LineNumberTable#12 = Utf8 LocalVariableTable#13 = Utf8 this#14 = Utf8 Lcom/joker/test/generic/Test;#15 = Utf8 main#16 = Utf8 ([Ljava/lang/String;)V#17 = Utf8 args#18 = Utf8 [Ljava/lang/String;#19 = Utf8 demo#20 = Utf8 Lcom/joker/test/generic/Demo;#21 = Utf8 id#22 = Utf8 Ljava/lang/Integer;#23 = Utf8 LocalVariableTypeTable#24 = Utf8 Lcom/joker/test/generic/Demo<Ljava/lang/Integer;>;#25 = Utf8 MethodParameters#26 = Utf8 SourceFile#27 = Utf8 Test.java#28 = NameAndType #8:#9 // "<init>":()V#29 = Utf8 com/joker/test/generic/Demo#30 = NameAndType #34:#35 // getId:()Ljava/lang/Object;#31 = Utf8 java/lang/Integer#32 = Utf8 com/joker/test/generic/Test#33 = Utf8 java/lang/Object#34 = Utf8 getId#35 = Utf8 ()Ljava/lang/Object;
{public com.joker.test.generic.Test();descriptor: ()Vflags: ACC_PUBLICCode:stack=1, locals=1, args_size=10: aload_01: invokespecial #1 // Method java/lang/Object."<init>":()V4: returnLineNumberTable:line 6: 0LocalVariableTable:Start Length Slot Name Signature0 5 0 this Lcom/joker/test/generic/Test;public static void main(java.lang.String[]);descriptor: ([Ljava/lang/String;)Vflags: ACC_PUBLIC, ACC_STATICCode:stack=2, locals=3, args_size=10: new #2 // class com/joker/test/generic/Demo3: dup4: invokespecial #3 // Method com/joker/test/generic/Demo."<init>":()V7: astore_18: aload_19: invokevirtual #4 // Method com/joker/test/generic/Demo.getId:()Ljava/lang/Object;12: checkcast #5 // class java/lang/Integer15: astore_216: returnLineNumberTable:line 9: 0line 10: 8line 11: 16LocalVariableTable:Start Length Slot Name Signature0 17 0 args [Ljava/lang/String;8 9 1 demo Lcom/joker/test/generic/Demo;16 1 2 id Ljava/lang/Integer;LocalVariableTypeTable:Start Length Slot Name Signature8 9 1 demo Lcom/joker/test/generic/Demo<Ljava/lang/Integer;>;MethodParameters:Name Flagsargs
}
SourceFile: "Test.java"
由反编译的文件可知:
- 声明侧的泛型被记录在Class文件的Constant pool中以Signature的形式保存
对于Java中泛型类型的获取可参考:Java中如何获取泛型类型信息
四、泛型使用
1. 泛型类
泛型类型用于类的定义中,被称为泛型类。用户在使用该类的时候,才把类型明确下来。
在类上定义的泛型,在实例方法中可以直接使用,不需要定义,但不能在静态方法中使用。
原因:Java中泛型只是一个占位符,必须在传递类型后才能使用。类实例化时才能正真的的传递类型参数,由于静态方法的加载先于类的实例化,也就是说类中的泛型还没有传递真正的类型参数静态的方法就已经加载完成了。
语法:
public class 类名<泛型表示符号> {
}
示例:
public class Test<T> {private T data;public T getData() {return data;}public void setData(T data) {this.data = data;}
}
如果使用时没指定具体的泛型类型,则泛型类型为Object。
public static void main(String[] args) {Test<String> test1 = new Test<>();String data1 = test1.getData();Test test2 = new Test();Object data2 = test2.getData();}
2. 泛型接口
泛型接口和泛型类的声明方式一致。泛型接口的具体类型需要在实现类中进行声明。
语法:
public interface 接口名<泛型标识符号> {
}
示例:
public interface TestInterface<T> {public T get();public void set(T t);
}
public class Test2 implements TestInterface<String> {@Overridepublic String get() {return null;}@Overridepublic void set(String s) {}
}
如果实现类未指定具体的泛型类型,则泛型类型为Object。
public class Test2 implements TestInterface{@Overridepublic Object get() {return null;}@Overridepublic void set(Object s) {}
}
3. 泛型方法
泛型类型声明在方法上,叫做泛型方法。
需要注意:只是在方法中使用类定义的泛型,该方法不是泛型方法。
语法:
public <泛型表示符号> void 方法名(泛型表示符号 参数名){
}public <泛型表示符号> 泛型表示符号 方法名(泛型表示符号 参数名){
}等......
示例:
public class Test {public static <T> void aaa(T t) {}public <T> void bbb(T t) {}
}
五、泛型扩展
1. 泛型的上下边界
泛型的上边界
泛型类型必须为指定类型的子类型。
格式:<? extends 类>
示例:
public class Test {public void aaa(List<? extends Number> t) {Number number = t.get(0);}public static void main(String[] args) {ArrayList<Integer> list = new ArrayList<>();list.add(1);Test test = new Test();test.aaa(list);}
}
泛型的下边界
泛型类型必须为指定类型的父类型。
格式:<? super 类>
示例:
public class Test {public void aaa(List<? super Number> t) {Object object = t.get(0);}public static void main(String[] args) {ArrayList<Object> list = new ArrayList<>();list.add(1);Test test = new Test();test.aaa(list);}
}
2. 泛型中使用&(并且)操作符
- 当需要多重约束的时候,可以使用&操作符
- &操作符只能放在泛型的声明上(泛型类、泛型接口、方法方法的声明上)
- &操作符后面只能是接口,不能是具体的类型,即使是Object也不行
- &操作符不能用于super上 ,因为java有规定
使用方式:
// 泛型类上申明,约束泛型类变量class WildcardTypeT<T extends Comparable<T> & List<T> & Serializable> {}// 方法上申明public <R extends Enum<R> & Serializable> List<R> parse2Enums(){}
https://blog.csdn.net/tianzhonghaoqing/article/details/119705014
相关文章:

Java泛型
文章目录一、泛型介绍1. 背景2. 概念3. 好处二、泛型声明泛型类型符号泛型声明方式三、类型擦除1. 什么是类型擦除桥接方法2. 为何需要类型擦除3. 类型信息并未完全擦除四、泛型使用1. 泛型类2. 泛型接口3. 泛型方法五、泛型扩展1. 泛型的上下边界泛型的上边界泛型的下边界2. 泛…...

07 分布式事务Seata使用(2)
1、Seata是什么 Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。AT模式是阿里首推的模式,阿里云上有商用版本的GTS&#x…...

c++练习题5
5.在C语言中,程序运行期间,其值不能被改变的量叫 常量 。 6.符号常量是指用一个符号名代表一个常量。 7.整型常量和浮点型常量也称为 数值常量 ,它们有正负之分。 9.在C中,变量是 其值可以改变的量 。 …...

Python 高级编程之正则表达式(八)
文章目录一、概述二、正则表达式语法1)字符匹配2)字符集合3)定位符4)分组1、定义分组2、引用分组3、命名分组三、Python 的 re 模块1)re.match() 方法2)re.search() 方法3)re.match() 与 re.sea…...

pynrrd常用操作解析
目录依赖安装官方文档常用操作1. 读部分nrrd.read()nrrd.read_header()nrrd.read_data()2. 写部分nrrd.write()依赖安装 pip install pynrrd官方文档 https://pynrrd.readthedocs.io/en/stable/ 常用操作 1. 读部分 nrrd.read() nrrdpath "your nrrd file path"…...

数据结构:链表基础OJ练习+带头双向循环链表的实现
目录 一.leetcode剑指 Offer II 027. 回文链表 1.问题描述 2.问题分析与求解 (1) 快慢指针法定位链表的中间节点 (2) 将链表后半部分进行反转 附:递归法反转链表 (3) 双指针法判断链表是否回文 二.带头双向循环链表的实现 1.头文件 2.节点内存申请接口和链表初始化接口…...

计算机视觉方向地理空间遥感图像数据集汇总
文章目录1.DSTL卫星图像数据集/Kaggle竞赛2.Swimming Pool and Car Detection/Kaggle竞赛3.SpaceNet Challenge 3数据集4.RarePlanes数据集5.BigEarthNet数据集6.NWPU VHR-10数据集7.UC Merced Land-Use数据集8.Inria Aerial Image Labeling数据集9.RSOD数据集1.DSTL卫星图像数…...

信息系统项目管理师真题精选(一)
1.信息系统的( )决定了系统可以被外部环境识别,外部环境或者其他系统可以按照预定的方法使用系统的功能或者影响系统的行为。A.可嵌套性B.稳定性C.开放性D.健壮性2、在实际的生产环境中,( )能使底层物理硬件…...

信息系统项目管理师刷题知识点(持续更新)
主要记录自己在备考高项过程中知识点 信息系统项目管理师刷题知识点(按刷题顺序排列) 1.信息技术应用是信息化体系六要素中的龙头,是国家信息化建设的主阵地,集中体现了国家信息化建设的需求和效益。 2.原型化方法也称为快速原型法…...

RabbitMq及其他消息队列
消息队列中间价都有哪些 先进先出 Kafka、Pulsar、RocketMQ、RabbitMQ、NSQ、ActiveMQ Rabbitmq架构 消费推拉模式 客户端消费者获取消息的方式,Kafka和RocketMQ是通过长轮询Pull的方式拉取消息,RabbitMQ、Pulsar、NSQ都是通过Push的方式。 pull类型…...

Toolformer: Language Models Can Teach Themselves to Use Tools
展示了LM可以通过简单的API教自己使用外部工具,并实现两个世界的最佳效果。我们介绍了Toolformer,这是一个经过训练的模型,可以决定调用哪些API,何时调用,传递哪些参数,以及如何将结果最好地纳入未来的标记…...

悲观锁与乐观锁
何谓悲观锁与乐观锁 乐观锁对应于生活中乐观的人总是想着事情往好的方向发展,悲观锁对应于生活中悲观的人总是想着事情往坏的方向发展。这两种人各有优缺点,不能不以场景而定说一种人好于另外一种人。 悲观锁 总是假设最坏的情况,每次去拿数据…...

LeetCode 25. K 个一组翻转链表
原题链接 难度:hard\color{red}{hard}hard 题目描述 给你链表的头节点 headheadhead , kkk 个节点一组进行翻转,请你返回修改后的链表。 kkk 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 kkk 的整数倍…...

朗润国际期货招商:历次科技风头下巨头的博弈
历次科技风头下巨头的博弈 VR/AR、区块链、折叠屏、元宇宙、AIGC五轮科技风头下巨头们都进场了吗? VR/AR硬件 谷歌:2014年入局,推出AR眼镜 百度:未入局 京东:未入局 腾讯:传要开发 亚马逊࿱…...

配置中心Config
引入依赖<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.6.RELEASE</version></parent><properties><spring-cloud.version>Finchley.SR…...

【原创】java+jsp+servlet学生信息管理系统(jdbc+ajax+filter+cookie+分页)
一直想写一个比较基础的JavaWeb项目,然后综合各种技术,方便Java入门者进行学习。学生信息管理系统大家一般接触的比较多,那么就以这个为例来写一个基础项目吧。 需求分析: 使用jspservletmysql开发的学生信息管理系统࿰…...

链表题目总结 -- 回文链表
目录一. 从中心开始找最大的回文字符串1. 思路简述2. 代码3. 总结二. 判断是否为回文字符串1. 思路简述2. 代码3.总结三. 判断是否是回文链表1. 思路简述2. 代码3. 总结4. 优化解法一. 从中心开始找最大的回文字符串 题目链接:没有。给定一个字符串s,从…...

JAVA集合之List >> Arraylist/LinkedList/Vector结构
在Java开发过程中,可能经常会使用到List作为集合来使用,List是一个接口承于Collection的接口,表示着有序的列表。而我们要讨论的是它下面的实现类Arraylist/LinkedList/Vector的数据结构及区别。 ArrayList ArrayList:底层为数组…...

Linux多进程开发
一、进程概述 1、程序和进程 程序是包含一系列信息的文件,这些信息描述了如何在运行时创建一个进程: 二进制格式标识:每个程序文件都包含用于描述可执行文件格式的元信息。内核利用此信息来解释文件中的其他信息。(ELF可执行连…...

三维重建小有基础入门之特征点检测基础
前言:本文将从此篇开始,记录自己从普通CVer入门三维重建的学习过程,可能过程比较坎坷,都在摸索阶段,但争取每次学习都能进一步,提高自己的能力,同时,每篇文章都会按情况相应地推出B站…...

基于node.js+vue+mysql考研辅导学习打卡交流网站系统vscode
语言 node.js 框架:Express 前端:Vue.js 数据库:mysql 数据库工具:Navicat 开发软件:VScode 主要功能包括管理员:首页、个人中心、用户管理、每日打卡管理、考研学校管理、考研专业管理、直通车管理、学习教材管理、…...

【C++、数据结构】封装unordered_map和unordered_set(用哈希桶实现)
文章目录📖 前言1. 复用同一个哈希桶⚡1.1 🌀修改后结点的定义1.2 🌀两个容器各自模板参数类型:2. 改造之后的哈希桶⛳3. 哈希桶的迭代器🔥3.1 💥哈希桶的begin()和 end(…...

StratoVirt 的 vCPU 拓扑(SMP)
CPU 拓扑用来表示 CPU 在硬件层面的组合方式,本文主要讲解 CPU 拓扑中的 SMP(Symmetric Multi-Processor,对称多处理器系统)架构,CPU 拓扑还包括其他信息,比如:cache 等,这些部分会在…...

现在直播大部分都是RTMP RTMP VS RTC
一 RTMP 抓了下抖音直播的包,windows端,走的TCP,加密了,估计还是RTMP。 我以为直播带货,都是RTC了。 快手直播也是TCP,地址用了IPV6。 淘宝直播也是。现在大部分直播都是RTMP。 只有视频会议走的RTC。…...

【Unity实战100例】Unity循环UI界面切换卡片功能
目录 编辑 一:制作UI界面 二:代码逻辑 1.定义基础变量...

Monorepo or 物料市场?结合工作实际情况对公司现有前端体系的思考
前言 去年年中基于若依vue前端框架进行了改造,加上后端的配合,我写了一套脚手架和项目中后台模板。中后台模板中包含了许多基础代码,比如登录/注册、路由、权限等等相关功能。这个中后台模板是基于我们实际开发定制的,所以跟通用…...

GEE学习笔记八十八:在自己的APP中使用绘制矢量(上)
在GEE中尤其是自己的APP中调用绘制的矢量图形方法之前没有合适的方法,但是现在可以通过ui.Map.DrawingTools(...)以及ui.Map.GeometryLayer(...)结合来做。具体的API如下图: 在这一篇中我先通过一个简单的例子来展示一下使用这些API后可以实现什么效果&a…...

“笨办法”学Python 3 ——练习 39. 字典,可爱的字典
练习39 源代码 # create a mapping of state to abbreviation #创建一个州与缩写的映射 states {Oregon:OR,Florida:FL,California: CA, New York: NY,Michigan:MI} #创建一个字典,key为州名,value为州缩写#Create a basic set of states and some cit…...

模糊的照片如何修复清晰?
相信有很多人用手机拍照时,觉得拍出来的照片一定是很漂亮的,结果拍了之后,拿出来一看模糊一片,根本看不清是什么。或者是只显示一半另一半模糊一片。而这些精彩瞬间很多时候是无法重拍的。虽然谁也不想拍出的照片出现模糊…...

如何理解session、cookie、token的区别与联系?
session、cookie、token。 相信学过接口的朋友都特别熟悉了。 但是对我一个刚接触接口测试的小白来说,属实有点分不清楚。 下文就是我通过查阅各种资料总结出来的一点理解,不准确的地方还请各位指正。 (文末送洗浴中心流程指南)…...