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

TypeScript 基础学习之泛型和 extends 关键字

b8fd221fb5967b382ea0fac973918c5a.gif

越来越多的团队开始使用 TS 写工程项目, TS 的优缺点也不在此赘述,相信大家都听的很多了。平时对 TS 说了解,仔细思考了解的也不深,借机重新看了 TS 文档,边学习边分享,提升对 TS 的认知的同时,也希望能在平时的工作中能用上,少写一点 any。

026813f6813fd567bbe8ba5c14d8d0f2.png

泛型

A major part of software engineering is building components that not only have well-defined and consistent APIs, but are also reusable. Components that are capable of working on the data of today as well as the data of tomorrow will give you the most flexible capabilities for building up large software systems.

In languages like C# and Java, one of the main tools in the toolbox for creating reusable components is generics, that is, being able to create a component that can work over a variety of types rather than a single one. This allows users to consume these components and use their own types.

我们工作的大部分内容是构建组件,定义有效、一致并且可复用的API很重要。组件能够处理当前的数据,又能考虑兼容很多未来的数据,这样的组件能提高工作效率,也能在构建软件系统的时候提供非常灵活的能力。

  基本使用

通过泛型可以定义通用的数据结构,增加 TypeScript 代码中类型的通用性。


  • 处理函数

先看一个具体的例子,感受一下泛型的应用。

首先定一个 log 函数,功能很简单把传入的参数直接 return 就行,函数参数类型是 string,那么返回值也是 string 类型。

function log(arg: string): string {return arg;
}

当其他地方也想使用这个函数,但是参数入参数类型是 number,这个时候我们也许可以这么做:

function log(arg: string | number): string | number {return arg;
}

当有更多的地方要使用这个函数的时候,那这个函数的参数类型定义和返回值类型定义将会变得无比冗长,或者可能就直接使用 any  来解决,当使用 any 的时候就失去了使用 TS 最初的初心了。

这个时候泛型出现了,能解决输入输出一致的问题,我们可以这样写:

function log<T>(arg: T): T {return arg;
}

这个 log 函数通过泛型来约束输入输出一致性的问题,把动态的泛型类型抛给函数的使用者,我们只需要保证输入输出的一致性就可以,还能支持任何类型。泛型中的 T 就像一个占位符,或者说一个变量,在使用的时候把定义的类型像参数一样传入就可以了。

我们在使用的时候可以有两种方式指定类型。第一,是直接定义要使用的类型,第二,是默认 TS 的类型推断,TS自动推导出要传入的类型:

log<string>('log')  // 定义 T 为 stringprint('log')  // TS 的类型推断,自动推导类型为 T 的类型为 string
  • 默认参数

在 JS 中对于一个函数入参,可以使用默认参数来简化当没有传参数时候的默认值,在 TS  中我们可以这样使用:

function log<T = string>(arg: T): T {return arg;
}

当没有传泛型参数的时候 T 的默认类型是 string 类型,就如果 JS 中的函数默认参数类似的用法

  • 多个参数

当函数中有多个参数的时候可以这样使用:

function log<T, U>(type: T, info: U): [T, U] {return [type, info];
}

通过在泛型定义多个对应位置的类型就可以获取到相应的泛型传参来对输入输出做一些处理。

  • 函数返回值

泛型不仅可以很方便地约束函数的参数类型,还可以用在函数执行副作用操作的时候。发送请求是我们使用的很多的操作,我们会有一个通用的发送请求的异步方法,请求不同的 url 会返回不同的类型数据,那么我们可以这样使用。

function request<T>(url: string): Promise<T> {return fetch(url).then(res => res.json())
}interface IUserInfo {name: string;age: number;avatar: string;gender: 'male' | 'female';city: string;
}request<IUserInfo>('/getuserinfo').then(res => {console.log(res)
});

这个时候返回的数据 TS 就会识别出 res 的类型,对解下来的代码编写会有很大帮助。

  应用

上面的一些小例子,我们对泛型有了一些了解,在平时我们可以这样使用。

  • 泛型约束类

定一个栈,有出栈和入栈两个方法,规定了出栈和入栈的元素类型必须一致。

class Stack<T> {private data: T[] = []push(item:T) {return this.data.push(item)}pop(): T | undefined {return this.data.pop()}
}
在使用的使用传入类型生成实例,在调用对应的出栈和入栈方法的时候入参数类型不对就会报错,从而约束了栈的元素类型。

const test1 = new Stack<number>()
const test2 = new Stack<string>()


  • 泛型约束接口

function request<T>(url: string): Promise<T> {return fetch(url).then(res => res.json())
}interface IUserInfo<T> {name: string;age: number;avatar: string;gender: 'male' | 'female';address: T;
}request<IUserInfo<string>>('/getuserinfo').then(res => {console.log(res)
});

这样使用 IUserInfo 的 address 的类型就是 string,让 interface 更灵活。

  • Pick

Pck 是 TS 内置的函数,作用是挑选出对象类型 T 中 U 对应的属性和类型,创建一个新的对象类型。

type Pick<T, K extends keyof T> = {[P in K]: T[P];
};interface IUserInfo {name: string;age: number;avatar: string;gender: 'male' | 'female';
}type Test = Pick<IUserInfo, 'name'> // { name: string }
  • Omit

与Pick的功能是互补的,挑选出对象类型 T 中不在 U 中的属性和类型,创建一个新的对象类型。

type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;interface IUserInfo {name: string;age: number;avatar: string;gender: 'male' | 'female';
}type Test = Omit<IUserInfo, 'name' | 'avatar' | 'gender'> // { age: number }

  总结

泛型,从字面上来理解,就是一般的,广泛的,具有通用性的。

泛型是指在定义函数、接口或类的时候,不预先指定具体类型,而是在使用的时候再指定类型。

泛型中的 T 就像一个占位符、或者说一个变量,在使用的时候可以把定义的类型像参数一样传入,它可以原封不动地输出。

8d13bb66decf36ff3af49425db89849a.png

extends

本文主要整理 extends 关键字在 typescript中的相关用法,平时在看一些复杂的 TS 类型的时候经常会看到使用 extends 这个关键字

  继承类型

TS 中的 extends 关键字第一个用法可以理解成 JS 中相似的用法继承类型。
interface IName {  name: string;
}interface IGender {gender: string;
}interface IPerson extends IName, IGender {age: number;
}const corgi: IPerson = {name: 'corgi',gender: 'female',age: 18,
}

以上示例中,IName 和 IGender 两个接口,分别定义了 name 属性和 gender 属性,IPerson 则使用extends 关键字多重继承的方式,继承了 IName 和 IGender,同时定义了自己的属性age,此时 IPerson 除了自己的属性外,还同时继承了 IName 和 IGender 的属性。


  条件判断

When the type on the left of the extends is assignable to the one on the right, then you’ll get the type in the first branch (the “true” branch); otherwise you’ll get the type in the latter branch (the “false” branch).

当 extends 左边的类型可以赋值给右边的类型时,你会在第一个分支中获取获得这个类型(true),否你会在第二个个分支中获得这个类型(false)

  • 普通条件类型

先来直接看个例子

// 示例1
interface IAnimal {name: string;
}interface IDog extends IAnimal {color: string;
}// A的类型为string
type Test = IDog extends IAnimal ? string : number;

extends 的条件判断和 JS 中的三元表达式很类似,如果问号前面的条件为真就把 string 类型赋值给 A,否则就把 number 类型赋值给 A。那么问号前面的条件判断真假的逻辑是什么呢?就像上面的那段英文描述一样,当extends 左边的类型可以赋值给右边的类型的时候,就会真,否则为假。

在上面的例子中,IDog 是 IAnimal 的子类,子类比父类的限制更多,如果能满足子类的条件约束,就一定能满足父类的条件约束,IDog 类型的值可以满足 IAnimal 类型,判断结果为真,Test 的类型为 string。

再来一个例子:

// 示例2
interface I1 {name: string
}interface I2 {name: stringage: number
}
// A的类型为string
type Test = I2 extends I1 ? string : number

这个例子,代入上面的解法来看就是,能满足 I2 类型约束的值也满足 I1 类型约束,判断结果为真,Test 的类型为 string。

多看几个例子:

type Test1 = 'x' extends 'x' ? "true" : "false";  // "true"
type Test2 = 'x' extends 'y' ? "true" : "false"  // "false"
type Test3 = 100 extends 100 ? "true" : "false"  // "true"
type Test4 = 200 extends 100 ? "true" : "false"  // "false"
type Test5 = {} extends {name:string} ? "true" : "false"  // "false"
type Test6 = {name:string} extends {} ? "true" : "false"  // "true"

按照上面的解释能够很好的解释出最后的结果。

  • 分配条件类型

再多看几个例子:

type Test1 = 'x' extends 'x' ? string : number; // string
type Test2 = 'x' | 'y' extends 'x' ? string : number; // numbertype P<T> = T extends 'x' ? string : number;
type Test3 = P<'x' | 'y'> // tring | numbertype P<T> = 'x' extends T ? string : number;
type Test4 = P<'x' | 'y'> // tring

这里就先把最后的结果直接给出来了,看到 Test1、Test2 和 Test4 还能理解,但是 Test3 的结果为什么就是 string |nunber这个类型了呢?同样的按照泛型传参数,按照直觉来说,Test3 和 Test2 应该是一样的结果,为什么结果差异这么大呢?

这里导致结果和直觉不一样的原因就是所谓的分配条件类型。

When conditional types act on a generic type, they become distributive when given a union type

当 extends 前面的参数是一个泛型类型,当传入的参数是一个联合类型的时候,就是使用分配律计算最后的结果,分配律就是我们从数学中学到的分配律。把联合类型中的每个类型代入条件判断得到每个类型的结果,再把每个类型的结果联合起来,得到最后的类型结果。

那么就可以按照这个解法来代入 Test3 的解释原因:

extends 前面的参数 T 是泛型参数,Test3 中 泛型代入的的 x | y这个联合类型,这个时候就触发了分配条件类型,来使用分配律

'x' extends 'x' ? string : number; // string
'y' extends 'x' ? string : number; // number
type Test3 = string | number

按照分配条件来看最后的结果恍然大悟,总之要触发分配条件类型要满足两个条件,第一,extends 前面的参数是泛型类型,第二,参数是联合类型。

条件分配类型是系统默认的行为,那么在某些需求不想要出发条件分配类型应该怎么办呢?

看下面的例子:

type P<T> = [T] extends ['x'] ? string : number;
type Test = P<'x' | 'y'> // number

这个使用使用了[]这个符号把泛型类型参数包起来,这个时候 extends 前面的参数就变成这个样子['x' | 'y'],不满足触发分配条件类型的条件,按照普通条件来判断,得到最后的结果为 number。


  • never

来个例子看看:

// never是所有类型的子类型
type Test1 = never extends 'x' ? string : number; // stringtype P<T> = T extends 'x' ? string : number;
type Test2 = P<never> // never

上面直接给出了最后的结果,但是为什么看起来 Test2 最后的结果又和直觉中不太一样,never 不是联合类型,直接代入条件类型之后,按理来说 Test2 和 Test1 的结果应该一样才对。

事实上,never 被认为是空的联合类型,也就是没有任何项的联合类型,所以还是满足上面的分配条件类型,因为没有任何联合项可以分配,所以P<T>根本就没有执行,就和永远没有返回的函数一样,属于 never 类型。

按照上面的条件,可以这样子来阻止分配条件类型。

type P<T> = [T] extends ['x'] ? string : number;
type Test = P<never> // string

  应用

  • Exclude

type Exclude<T, U> = T extends U ? never : T;

Exclude 是 TS 内置的应用方法,作用是从第一个联合类型参数 T 中,把第二个联合类型参数 U 出现的联合项去掉。

type Test = Exclude<'A' | 'B', 'A'> // 'B'

其实就是应用了分配条件类型:

type Test = Exclude<'A', 'A'> | type Test = Exclude<'B', 'A'>type Test = 'A' extends 'A' ? never : 'A' | 'B' extends 'A' ? never : 'B'
type Test = never | 'B'
type Test = 'B'
  • Extract

type Exclude<T, U> = T extends U ? T : never;

Extract 是 TS 内置的应用方法,作用是从第二个联合类型参数 U 中,把第一个联合类型参数 T 出现的联合项提取出来。

type Test = Exclude<'A' | 'B', 'A'> // 'A'

其实就是应用了分配条件类型。

type Test = Exclude<'A', 'A'> | type Test = Exclude<'B', 'A'>
type Test = 'A' extends 'A' ? 'A' : never | 'B' extends 'A' ? 'B' : never
type Test = 'A' | never
type Test = 'A'

  总结

在 typescript 中的 extends 关键字主要用法,就是继承类型,结合三元表达式来完成更多的类似函数的应用方法,在三元表达式中还要注意分配条件类型的应用。

文章为笔者在学习过程中做的笔记,如果有误,欢迎指正。

2c00ebab2d61f4faab500dcbfe6056f7.png

团队介绍

我们是大淘宝技术行业与商家技术团队,是消费电子线下业务,主要面向线下门店的分销、经营、零售相关的产品。技术侧属于大淘宝技术前端团队,技术产品服务阿里巴巴整个集团亿万级别的业务。

¤ 拓展阅读 ¤

3DXR技术 | 终端技术 | 音视频技术

服务端技术 | 技术质量 | 数据算法

相关文章:

TypeScript 基础学习之泛型和 extends 关键字

越来越多的团队开始使用 TS 写工程项目&#xff0c; TS 的优缺点也不在此赘述&#xff0c;相信大家都听的很多了。平时对 TS 说了解&#xff0c;仔细思考了解的也不深&#xff0c;借机重新看了 TS 文档&#xff0c;边学习边分享&#xff0c;提升对 TS 的认知的同时&#xff0c;…...

《数据分析-JiMuReport04》JiMuReport报表设计入门介绍-页面优化

报表设计 2 页面优化 如上图所示的报表&#xff0c;仅仅是展示数据&#xff0c;不过这样看起来似乎太草率了&#xff0c;所以再优化一下吧 保存报表后&#xff0c;在积木报表中就可以看到对应的报表文件 此时我们如果还需要编辑报表&#xff0c;就点击这个报表即可 2.1 居中…...

带头双向循环链表及链表总结

1、链表种类大全 1、链表严格来说可能用2*2*28种结构&#xff0c;从是否带头&#xff0c;是否循环&#xff0c;是否双向三个角度区分。 2、无头单向循环链表一般不会在实际运用中直接存储数据&#xff0c;而会作为某些更复杂结构的一个子结构&#xff0c;毕竟它只在头插、头删…...

(八十)MySQL是如何基于各种规则去优化执行计划的?(中)

今天我们来讲一下子查询是如何执行的&#xff0c;以及他的执行计划是如何优化的。比如说类似于下面的SQL语句&#xff1a; select * from t1 where x1 (select x1 from t2 where idxxx) 这就是一个典型的子查询 也就是说上面的SQL语句在执行的时候&#xff0c;其实会被拆分为…...

第一章:命题与命题公式

1.命题与命题联结词 1.命题与命题的表示 1. 命题 由一个或几个已知的前提,推导出来一个未知的结论的思维过程称为推理,推理的基本要素就是表达这些前提的一些陈述句,可以将这些陈述句理解为命题。 (1)地球是行星 (2)8不是素数 (3)1 + 2 = 22. 命题真值 一个陈述句不…...

c/c++开发,无可避免的操作符operator(篇一),操作符重载

一、操作符号重载 虽然c/c内置了大量各类操作符&#xff0c;开发者可以很方便将其应用数学运算、成员访问、类型转换、内存分配等执行语句中&#xff0c;但很多时候&#xff0c;也需要根据项目应用需要&#xff0c;通过操作符重载&#xff0c;能够针对类类型的操作数定义不同的…...

【7.MySQL行格式存储】

1.MySQL数据存放文件 我们每创建一个 database&#xff08;数据库&#xff09; 都会在 /var/lib/mysql/ 目录里面创建一个以 database 为名的目录,创建一个student表 [rootxiaodainiao ~]#ls /var/lib/mysql/my_test db.opt student.frm student.ibddb.opt&#xff1a;用…...

【Linux】线程实例 | 简单线程池

今天来写一个简单版本的线程池 1.啥是线程池 池塘&#xff0c;顾名思义&#xff0c;线程池就是一个有很多线程的容器。 我们只需要把任务交到这个线程的池子里面&#xff0c;其就能帮我们多线程执行任务&#xff0c;计算出结果。 与阻塞队列不同的是&#xff0c;线程池中内有…...

ATAC-seq 数据分析实战

文章目录一、 ATAC-seq原理和基础知识1. ATAC-seq原理2. Tn5转座子1. 转座概念2. 参与分子1. 转座子&#xff08;1&#xff09; 简化的转座子结构&#xff08;2&#xff09; Tn5转座子的结构2. 转座酶3. 转座过程二、数据比对和过滤一、 ATAC-seq原理和基础知识 1. ATAC-seq原…...

设计模式-第13章(状态模式)

状态模式状态模式状态模式的好处和用处工作状态状态模式 状态模式&#xff08;State&#xff09;&#xff0c;当一个对象的内在状态改变时允许改变其行为&#xff0c;这个对象看起来像是改变了其类。 状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况…...

ReentrantLock源码分析(一)加锁流程分析

一、ReetrantLock的使用示例 static ReentrantLock lock new ReentrantLock(); public static void main(String[] args) throws InterruptedException { new Thread(ClassLayOutTest::reentrantLockDemo, "threadA").start(); Thread.sleep(1000);…...

【C++】list的模拟实现

文章目录1.list 底层2. list的模拟实现1. list_node 类设计2. list类如何调用类型3 .push_back(正常实现)4. 迭代器的实现第一个模板参数Tconst迭代器第二个模板参数Ref第三个模板参数Ptr对list封装的理解5. insert6.push_back与 push_front(复用)7. erase8. pop_back与pop_fro…...

Python连接es笔记三之es更新操作

这一篇笔记介绍如何使用 Python 对数据进行更新操作。 对于 es 的更新的操作&#xff0c;不用到 Search() 方法&#xff0c;而是直接使用 es 的连接加上相应的函数来操作&#xff0c;本篇笔记目录如下&#xff1a; 获取连接update()update_by_query()批量更新UpdateByQuery()…...

哪个牌子的蓝牙耳机音质好?音质比较好的蓝牙耳机排名

蓝牙耳机经过多年发展&#xff0c;无论是在外观设计还是性能配置上都有很大的进步&#xff0c;越来越多的蓝牙耳机开始注重音质表现&#xff0c;逐渐有HIFI音质、无损音质出现在大众视野。那么哪个牌子的蓝牙耳机音质好&#xff1f;接下来&#xff0c;我来给大家分享几款音质比…...

Qt实用技巧:Qt中浮点数的相等比较方式(包括单精度和双精度)

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/129464152 红胖子(红模仿)的博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软…...

【数据结构初阶】双向循环链表

目录一.链表的分类二.与单链表相比三.实现增删查改1.双向循环链表结构的创建2.创建新节点3.初始化链表4.头插和尾插5.判断链表是否为空6.头删和尾删7.打印函数8.查找函数9.删除pos位置节点10.在pos前位置插入数据11.优化升级一.链表的分类 链表可有根据单向双向、有无哨兵位、…...

0104BeanDefinition合并和BeanClass加载-Bean生命周期详解-spring

文章目录1 前言2 BeanDefinition合并2.1 BeanDefinition合并在做什么&#xff1f;2.2 BeanDefinition怎么合并2.3 示例演示3 Bean Class 加载后记1 前言 下面要介绍的阶段&#xff0c;都是在调用getBean()从容器中获取bean对象的过程中发生的操作&#xff0c;我们需要更多的去…...

Java集合进阶(三)

文章目录一、Map1. 概述2. 基本功能3. 遍历4. 遍历学生对象5. 集合嵌套6. 统计字符出现次数二、Collections1. 常用方法2. 学生对象排序三、模拟斗地主一、Map 1. 概述 Interface Map<K, V>&#xff1a;K 是键的类型&#xff0c;V 是值的类型。 将键映射到值的对象&…...

【网络】什么是RPC?RPC与HTTP有什么关系?

文章目录RPC是什么RPC和HTTP的关系和区别[附]关于REST论文中提到的"HTTP不是RPC"重点参考 凤凰架构-远程过程调用 既然有HTTP为什么还要有RPC&#xff1f; RPC是什么 RPC(Remote Procedure Call)&#xff1a;即远程过程调用&#xff0c;目的是为了让计算机能够跟调用…...

[手撕数据结构]栈的深入学习-java实现

CSDN的各位uu们你们好,今天千泽带来了栈的深入学习,我们会简单的用代码实现一下栈, 接下来让我们一起进入栈的神奇小世界吧!0.速览文章一、栈的定义1. 栈的概念2. 栈的图解二、栈的模拟实现三.栈的经典使用场景-逆波兰表达式总结一、栈的定义 1. 栈的概念 栈&#xff1a;一种…...

2.线性表的顺序表示

数据结构很重要&#xff01; 数据结构很重要&#xff01;&#xff01;&#xff01; 数据结构很重要&#xff01;&#xff01;&#xff01;&#xff01; 思考 1.线性表的顺序表示内容有哪些&#xff1f;&#xff08;What&#xff09; 2.为什么要学线性表的顺序表示? ? (Why)…...

eps文件删除了能恢复吗?恢复误删eps文件的三种方法

eps文件格式专为矢量图像和图形而设计。虽然没有被广泛使用&#xff0c;但它仍然受到各种插画家和平面设计师的钟爱。eps文件十分适合创建徽标和商标设计&#xff0c;主要应用见于广告牌、海报和横幅。可是在使用设备过程中&#xff0c;难免会遇到数据丢失问题&#xff0c;如果…...

【C++】运算符重载练习——Date 类

文章目录&#x1f449;日期类介绍&#x1f448;&#x1f449;日期类实现&#x1f448;&#x1f4d5; 成员变量&#x1f4d5; 构造函数&#x1f4d5; 对应月份天数&#x1f4d5; 赋值重载&#x1f4d5; 比较运算符重载&#x1f4d5; 计算 运算符重载&#x1f449;源代码&#x1…...

Redis学习(13)之Lua脚本【环境准备】

文章目录一 Lua入门环境准备1.1 Lua简介1.2 Linux 系统安装Lua1.2.1 Lua 下载1.2.2 Lua 安装1.3 Hello World1.3.1 命令行模式1.3.2 脚本文件模式1.3.3 两种脚本运行方式1.4 Win安装Lua1.4.1 LuaForWindows的安装1.4.2 SciTE修改字体大小1.4.3 SciTE中文乱码1.4.4 SciTE快捷键工…...

关于BLE的一些知识总结

数据包长度对于BLE4.0/4.1来说&#xff0c;一个数据包的有效载荷最大为20字节对于BLE4.2以上&#xff0c;数据包的有效载荷扩大为251字节传输速率在不考虑跳频间隔的情况下&#xff0c;最大传输速率为&#xff1a;1&#xff09;BLE4.0/4.1的理论吞吐率为39kb/s&#xff1b;2&am…...

Spring框架源码分析一

如何看源码&#xff08;方法论&#xff09;不要忽略源码中的注释使用翻译工具先梳理脉络&#xff0c;然后梳理细节即总分总&#xff0c;先总体过一遍&#xff0c;再看细节&#xff0c;再做一个总结大胆猜测&#xff08;8分靠猜&#xff09;&#xff0c;小心验证&#xff0c;再调…...

CSS常用内容总结(扫盲)

文章目录前言相关概念【了解】脚本语言什么是脚本语言脚本语言有什么特点常见的脚本语言什么是动态语言&#xff0c;什么是静态语言动态语言和静态语言两者之间有何区别CSSCSS是什么CSS的特点一、CSS代码怎么写基本语法规则引入方式内部样式内联样式表外部样式代码风格二、CSS的…...

Java启蒙之语言基础

目录 一.Java标识符和关键字 1.1Java标识符 1.2Java关键字 二.数据类型和变量的概述和关系 2.1Java变量 2.2Java的数据类型 2.2.1数据类型的分类的概述 2.2.2数据类型的转换 3.Java运算符 总结 &#x1f63d;个人主页&#xff1a;tq02的博客_CSDN博客-领域博主 &#…...

数据库系统--T-SQL数据查询功能-多表查询(超详细/设计/实验/作业/练习)

目录课程名&#xff1a;数据库系统内容/作用&#xff1a;设计/实验/作业/练习学习&#xff1a;T-SQL数据查询功能-多表查询一、前言二、环境与设备三、内容四、内容练习题目&#xff1a;对应题目答案&#xff1a;五、总结课程名&#xff1a;数据库系统 内容/作用&#xff1a;设…...

Spring Boot 3.0系列【14】核心特性篇之Configuration相关注解汇总介绍

有道无术,术尚可求,有术无道,止于术。 本系列Spring Boot版本3.0.3 源码地址:https://gitee.com/pearl-organization/study-spring-boot3 文章目录 前言@Configuration@ConfigurationProperties@EnableConfigurationProperties@ConfigurationPropertiesScan@Configuratio…...

[ubuntu][jetson]给jetson增加swap空间类似于给windows加虚拟内存

具体操作如下&#xff1a; #打开性能模式 sudo nvpmodel -m 0 && sudo jetson_clocks #增加swap空间&#xff0c;防止爆内存 swapoff -a sudo fallocate -l 15G /swapfile sudo chmod 600 /var/swapfile sudo mkswap /swapfile sudo swapon /swapfile…...

小黑子—Java从入门到入土过程:第二章

Java零基础入门2.0Java系列第二章1. 注释和关键字2. 字面量3. 变量3.1 基本用法3.2 使用方式3.3 注意事项4. 变量练习5. 计算机中的数据存储5.1 计算机的存储规则5.2 进制5.3 进制间转换二进制转十八进制转十十六进制转十十进制转其他进制6. 数据类型7. 定义变量的练习8. 标识符…...

ElasticSearch搜索详细讲解与操作

全文检索基础 全文检索流程 流程&#xff1a; #mermaid-svg-7Eg2qFEl06PIEAxZ {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-7Eg2qFEl06PIEAxZ .error-icon{fill:#552222;}#mermaid-svg-7Eg2qFEl06PIEAxZ .error…...

web实现太极八卦图、旋转动画、定位、角度、坐标、html、css、JavaScript、animation

文章目录前言1、html部分2、css部分3、JavaScript部分4、微信小程序演示前言 哈哈 1、html部分 <div class"great_ultimate_eight_diagrams_box"><div class"eight_diagrams_box"><div class"eight_diagrams"><div class&…...

【LeetCode】33. 搜索旋转排序数组、1290. 二进制链表转整数

作者&#xff1a;小卢 专栏&#xff1a;《Leetcode》 喜欢的话&#xff1a;世间因为少年的挺身而出&#xff0c;而更加瑰丽。 ——《人民日报》 目录 33. 搜索旋转排序数组 1290. 二进制链表转整数 33. 搜索旋转排序数组 33. 搜索旋转排序…...

IBM Semeru Windows 下的安装 JDK 17

要搞清楚下载那个版本&#xff0c;请参考文章&#xff1a;来聊聊 OpenJDK 和 JVM 虚拟机下载地址semeru 有认证版和非认证版&#xff0c;主要是因为和 OpenJ9 的关系和操作系统的关系而使用不同的许可证罢了&#xff0c;本质代码是一样的。在 Windows 下没有认证版&#xff0c;…...

Lambda表达式和steram流

目录 引言&#xff1a; 语法: Lambda 表达式实例&#xff1a; demo演示&#xff1a; Stream流&#xff1a; 引言&#xff1a; Lambda 表达式&#xff0c;也可称为闭包&#xff0c;它是推动 Java 8 发布的最重要新特性。 Lambda 允许把函数作为一个方法的参数&#xff08;函…...

面试必会-MySQL篇

1. Mysql查询语句的书写顺序Select [distinct ] <字段名称>from 表1 [ <join类型> join 表2 on <join条件> ]where <where条件>group by <字段>having <having条件>order by <排序字段>limit <起始偏移量,行数>2. Mysql查询语…...

Hadoop入门常见面试题与集群时间同步操作

目录 一&#xff0c;常用端口号 Hadoop3.x &#xff1a; Hadoop2.x&#xff1a; 二&#xff0c;常用配置文件&#xff1a; Hadoop3.x: Hadoop2.x: 集群时间同步&#xff1a; 时间服务器配置&#xff08;必须root用户&#xff09;&#xff1a; &#xff08;1&#xff09…...

JS 数组去重的方法

// 数组去重 const arr ["1", "1", "2", "3", "5", "3", "1", "5", "4"] console.log(this.deduplicate(arr)) // [1, 2, 3, 5, 4] // 数组对象去重 const arr [ { id: 1, nam…...

PMP项目管理项目沟通管理

目录1 项目沟通管理2 规划沟通管理3 管理沟通4 监督沟通1 项目沟通管理 项目沟通管理包括通过开发工件&#xff0c;以及执行用于有效交换信息的各种活动&#xff0c;来确保项目及其相关方的信息需求得以满足的各个过程。项目沟通管理由两个部分组成&#xff1a;第一部分是制定…...

2.JVM常识之 运行时数据区

1.JVM核心组成 2.JVM 运行时数据区&#xff08;jdk8&#xff09; 程序计数器&#xff1a;线程私有&#xff0c;当前线程所执行字节码的行号指示器 jvm栈&#xff1a;线程私有&#xff0c;Java 虚拟机栈为 JVM 执行 Java 方法服务 本地方法栈&#xff1a;线程私有&#xff0c;本…...

你的游戏帐号是如何被盗的

据报道&#xff0c;2022上半年&#xff0c;中国游戏市场用户规模达到了5.54亿人&#xff0c;游戏市场销售收入1163.1亿元&#xff0c;相较去年均为同比增长的情况。如此庞大的市场规模&#xff0c;黑色产业链是绕不开的话题。 但相较于游戏中大家常见的玩家与玩家、玩家与官方…...

C++11异步编程

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录前言1、std::future和std::shared_future1.1 std:future1.2 std::shared_future2、std::async3、std::promise4、std::packaged_task前言 C11提供了异步操作相关的类…...

20230310----重返学习-DOM元素的操作-时间对象-定时器

day-024-twenty-four-20230310-DOM元素的操作-时间对象-定时器 复习 获取元素 id document.getElementById() 类名 document.getElementsByClassName() 标签名 document.getElementsByTagName() name属性 document.getElementsByName() 选择器 document.querySelector()docum…...

江苏专转本转本人后悔排行榜

江苏专转本转本人后悔排行榜 一、复习的太迟&#xff1a; 后悔指数:五颗星。 复习越到最后&#xff0c;时间一天天变少&#xff0c;要复习的内容还有很多&#xff0c;很多人都后悔没有早早开始&#xff0c;总想着多给我两月一定会考上的。 担心时间不够用&#xff0c;那就努力利…...

【算法时间复杂度】学习记录

最近开算法课&#xff0c;开几篇文章记录一下算法的学习过程。 关于算法的重要性 学习计算机当程序员的话&#xff0c;在编程过程中是绕不开算法这个大矿山的&#xff0c;需要我们慢慢挖掘宝藏。 算法&#xff08;Algorithm&#xff09;是指用来操作数据、解决程序问题的一组…...

汽车车机芯片Linux系统内核编译问题总结

谈到车机,很多人会想到华为问界上装的大屏车机,号称车机的天花板,基于鸿蒙OS的,而今天谈到的车机芯片用的是linux内核Kernel,对于它的编译,很多人一时会觉得头大,的确如果工具不是很齐全,就会遇到这样那样的问题,但是过程都会有错误提示,按照错误提示基本可以解决,而…...

Android13 音量曲线调整

Android13 音量曲线调整 Android13 上配置文件的路径&#xff1a; /vendor/sprd/modules/audio/engineconfigurable_apm/工程目录/system/etc/audio_engine_config/audio_policy_engine_stream_volumes.xml /vendor/sprd/modules/audio/engineconfigurable_apm/工程目录/sys…...

OpenHarmony通过MQTT连接 “改版后的华为IoT平台”

一、前言 本篇文章我们使用的是BearPi-HM_Nano开发板:小熊派的主板+E53_IA1扩展板 源码用的是D6_iot_cloud_oc,点击下载BearPi-HM_Nano全量源码 那么为什么要写这篇呢? 前段时间看到OpenHarmony群里,经常有小伙伴问接入华为IoT平台的问题,他们无法正常连接到华为IoT平台等…...