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

【java基础】一篇文章彻底搞懂lambda表达式

文章目录

  • lambda表达式是什么
  • lambda表达式的语法
  • 函数式接口
    • 初次使用
    • 深入理解
  • 方法引用 :: 用法
    • 快速入门
    • 不同形式的::
      • 情况1 object::instanceMethod
      • 情况2 Class::instanceMethod
      • 情况3 Class::staticMethod
    • 对于 :: 的一些示例及其注意事项
  • 构造器引用
  • 变量作用域
    • 使用外部变量
    • 定义内部变量
    • this指向问题
  • lambda的好处
  • 常见的函数式接口
  • 自己设计一个支持lambda的方法
  • 自定义函数式接口
  • 总结

lambda表达式是什么

lambad表达式是一个可传递的代码块,可以在以后执行一次或者多次。

我们都知道java是面向对象的语言,我们在进行方法传递时,并不能直接传递代码段,而是要传递一个对象,这个对象中有一个方法包含了想要传递的代码段。

例如Arrays.sort就要一个Comparator接口,我们就只能传递一个实现该接口的对象。

        Integer[] nums = {4, 1, 3, 2};Arrays.sort(nums, new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {return o2 - o1;}});

在其他一些语言中,可以直接处理代码块,但是java一直没有增加这个特性,因为java的强大之处就在于其简单性和一致性。好在在jdk8中加入了一种lambad的设计,我们可以使用lambda就可以实现类似代码块传递的功能,极大的简化了代码。
我们上面的代码使用lambad就可以改写为如下形式

        Integer[] nums = {4, 1, 3, 2};Arrays.sort(nums, (o1, o2) -> o2 - o1);

lambda表达式的语法

这里我先简单说明一下,lambda表达式其实就是用来实现某个抽象方法的,并且某个抽象类或者接口只有一个抽象方法才能使用lambda表达式。下面的例子也是基于String类型的Comparator中的compare抽象方法

在这里插入图片描述

lambda的语法就是 (参数) -> {代码逻辑}
我们利用lambda来实现方法,一个简单的例子如下

		(String s1, String s2) -> {return s1.length() - s2.length();};

如果代码块里面只有一行语句,那么就可以省略大括号,直接写在一行

(String s1, String s2) -> s1.length() - s2.length();

写在一行就可以省略return关键字了
关于lambda并不是一定要有返回值,是否要有返回值是却决于要实现的抽象方法是否有返回值的。

对于一个lambda方法,在很多情况下都是可以省略参数上面的类型的,因为编译器可以推断出

(s1, s2) -> s1.length() - s2.length();

对于只有一个参数的lambda,我们可以省略参数的括号。对于没有参数的lambda我们又必须要写上该括号

s -> s.length();
() -> System.out.println(1);

这里介绍了lambda的一些形式,看不懂不要紧,下面就开始具体说明。

函数式接口

对于只有一个抽象方法的接口,需要这种接口的对象时,我们就可以提供一个lambda表达式。这种接口就称为函数式接口。

初次使用

我们还是来看一下Arrays.sort方法

在这里插入图片描述
该sort方法就需要提供一个实现Comparator的接口。下面再来看一下Comparator接口

在这里插入图片描述
这个接口有很多方法,但是只有compare是抽象方法,其他都有默认实现,所以这个就符合函数式接口的定义,我们使用Arrays.sort方法时,就不需要传入一个实现Comparator的对象,只需要传入一个lambda的表达式就行了。

下面就是使用lambda就行排序的例子

public class People {private String name;private Integer age;public People(String name, Integer age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}@Overridepublic String toString() {return "People{" +"name='" + name + '\'' +", age=" + age +'}';}
}

我们有一个People对象数组,现在要求对这个数组进行排序,排序要求为按照名称的长度排序,升序

        People[] people = {new People("cc", 19),new People("ttpfx", 21),new People("tom", 26),new People("lucy", 20)};

我们要使用lambda表达式,首先要搞清楚用lambda所对应的抽象方法,我们这里要实现的方法就是compare方法,传入2个参数,返回一个int
在这里插入图片描述
这里的T就是一个泛型,由于我们是对People排序,所以T就是代表People对象。知道了这些,我们就可以写lambda表达式了。

Arrays.sort(people, (p1, p2) -> p1.getName().length() - p2.getName().length());

上面的代码就可以实现People数组按照名称长度升序排列

对应lambda表达式,我们最好将其看作是一个函数,而不是一个对象。

深入理解

对于上面lambda表达式,我们还可以简写,形式如下

Arrays.sort(people, Comparator.comparingInt(p -> p.getName().length()));

对于上面的表达式,我来进行说明一下,由于Arrays.sort需要一个Comparator,所以我们需要提供一个Comparator,但是Comparator.comparingInt会返回一个Comparator。所以没问题

在这里插入图片描述

又由于comparingInt需要接受一个ToIntFunction,我们再来看一下ToIntFunction

在这里插入图片描述

可以发现ToIntFunction就只有一个抽象方法,所以我们又可以使用lambda表达式,最终的形式就是下面那样的。

Arrays.sort(people, Comparator.comparingInt(p -> p.getName().length()));

对于泛型,默认大家都是很了解的,这篇文章不会进行讲解,如果感觉有点看不懂了,请先去学习泛型

方法引用 :: 用法

快速入门

有的时候,如果我们lambda涉及到一个方法,例如我们创建了一个定时器,要求每秒打印一下这个事件对象,代码如下

Timer timer = new Timer(1000, event -> System.out.println(event));

这里为什么可以使用lambda表达式,大家应该都可以猜出来了,原因就是Timer的第二个参数是应该函数式接口,只有一个抽象方法,Timer的第二个参数内容如下。

在这里插入图片描述

对于上面的写法我们可以简写为如下形式

Timer timer = new Timer(1000, System.out::println);

对于 System.out::println 这个写法可能已经很多人蒙了,这是啥东西啊。其实 System.out::println 就是一个方法引用,就代表引用System.out对象的println方法。System.out::println指示编译器生成一个函数式接口的实例,覆盖这个接口的抽象方法来调用给定的方法。相信大家看完还是很蒙,下面就再通俗的解释一下。

  • 我们通过ActionListener源代码可以发现actionPerformed会传入一个 ActionEvent对象 e,返回值为void,也就是没有返回值。
  • 我们再来看一下System.out的println的方法
    在这里插入图片描述
    可以发现println接受一个Object的参数,返回值也是void
  • 我们将 actionPerformed 和 println 进行对比,是不是发现很相似呢?对于actionPerformed 的参数,我们也可以通过Object来进行接收。
  • 我们再lambda表达式里面编写的逻辑就是打印参数,println的任务就是打印,既然如此,那为什么我们不直接将println这个方法用来覆盖actionPerformed 掉方法呢?
  • 事实上System.out::println,我们就是用println方法覆盖掉了actionPerformed 方法,我们调用actionPerformed(e)时,实际上就是调用println(e)方法了。

对于上面的说明,仅仅为个人的理解。如果有误还请在评论区指出。

如果要使用 :: 形式的lambda表达式,必须返回值相同,参数个数相同,参数类型相同或者为父类

不同形式的::

对于使用::分隔方法名与对象名或类名,主要有以下3种情况

  • object::instanceMethod
  • Class::instanceMethod
  • Class::staticMethod

情况1 object::instanceMethod

在第一种情况下,方法引用等价于向方法传递参数的lambda的表达式。例如上面的System.out::printl1n就等价于 x -> System.out.println(x)

情况2 Class::instanceMethod

对于这种情况,我先举一个例子,现在有一个要求就是对String数组按照字母升序排列,忽略大小写

        String[] names = {"Tom", "CC", "tTpfx", "JURY"};

对于上面的要求,经过上面要求,我们该怎么完成呢?通过上面的lambda的学习,我们可以通过lambda表达式完成,我们调用compareToIgnoreCase这个方法进行比较就行了

        Arrays.sort(names, (name1, name2) -> name1.compareToIgnoreCase(name2));

我们来看一下compareToIgnoreCase的源代码

在这里插入图片描述
可以发现这个和我们要传入Comparator的compare方法参数和返回类型都是一样,这样那我们岂不是就可以使用::的写法了。也确实是这样的。::写法如下

        Arrays.sort(names, String::compareToIgnoreCase);

可以发现十分的简洁。

经过上面的例子,现在就可以对上面的 Class::instanceMethod 进行说明了,Class就代表类名,instanceMethod 就代表静态方法。对于这种情况,第一个参数就会成为隐式参数。也就是说String::compareToIgnoreCase 相当于 (name1, name2) -> name1.compareToIgnoreCase(name2)

情况3 Class::staticMethod

这种情况就不举例了,理解了情况2现在来理解这个很简单。Class::staticMethod就相当于将所有参数传递到参数列表,例如 Math::pow 就等价于 (a,b) -> Math.pow(a,b)

对于 :: 的一些示例及其注意事项

下图就是::的一些示例

在这里插入图片描述

对于::的注意事项如下

  • 只有当lambda表达式的体只调用一个方法并且不做其他操作时,才可以把lambda表达式重写为方法引用
  • 如果要引用的方法具有多个重载的方法,编译器会找出最相似的方法
  • 方法引用不能单独存在,总是会转换为函数式接口的实例
  • 包含对象的方法引用与等价的lambda表达式还有一个细微的差别。考虑一个方法法引用,如separator::equals.。如果separator为null,构造separator::equals时就会立抛出一个异常。lambda表达式x -> separator.equals(x)只在调用时才会拋出NullPointerException。
  • 对于::我们可以使用this和super,this代表当前类,super表示父类

构造器引用

构造器引用和方法引用很类似,只不过将方法名换成了new,下面就是应该例子

public class Cat {public Cat() {}public Cat(Cat cat) {}
}

下面代码将一个集合转换为数组

    @Testpublic void t4() {List<Cat> list = new ArrayList<>();list.add(new Cat());list.add(new Cat());Stream<Cat> stream = list.stream().map(Cat::new);Cat[] cats = stream.toArray(Cat[]::new);System.out.println(Arrays.toString(cats));}

里面的第一个Cat::new 就代表引用构造器。相当于 c -> new Cat©
第二个Cat[]::new 相当于 x -> new Cat[x]

变量作用域

使用外部变量

在lambda表达式中,我们使用的外部变量必须是最终变量或实际上的最终变量。
例如下面代码是没有问题的

    @Testpublic void t1() {int i = 1;Integer[] nums = {2, 1, 3};Arrays.sort(nums, (n1, n2) -> {System.out.println(i);return n2 - n1;});System.out.println(Arrays.toString(nums));}

我们在lambda里面打印i的值,没有任何问题。但是我们如果将i的值改变

    @Testpublic void t1() {int i = 1;Integer[] nums = {2, 1, 3};i++;Arrays.sort(nums, (n1, n2) -> {System.out.println(i);return n2 - n1;});System.out.println(Arrays.toString(nums));}

此时再运行,编译器就会输出如下信息

在这里插入图片描述

IDEA也会给出以下提示,告诉我们变量的值是不能够改变的

在这里插入图片描述

定义内部变量

对于lambda表达式,我们再里面还不能够定义与外部变量相同的参数名称,例如下面代码

    @Testpublic void t1() {int i = 1;Integer[] nums = {2, 1, 3};Arrays.sort(nums, (n1, n2) -> {int i = 0;return n2 - n1;});System.out.println(Arrays.toString(nums));}

我们再lambda里面定义了与外部变量同名的i变量,这时候IDEA就会给出以下提示

在这里插入图片描述

如果运行就会报错

在这里插入图片描述

this指向问题

在lambda里面的this就是创建lambda那个方法的this。

    @Testpublic void t2() {Integer[] nums = {2, 1};System.out.println(this.getClass().hashCode());Arrays.sort(nums, (n1, n2) -> {System.out.println(this.getClass().hashCode());return n2 - n1;});}

上面代码输出如下

在这里插入图片描述
也就代表这两个this是一样的。

lambda的好处

我们使用lambda的重点就是延迟执行,lambda只有在调用时才会执行。对于为什么需要延迟执行,参考下面的几点

  • 在一个单独的线程中运行代码
  • 多次运行代码
  • 在算法的适当位置运行代码(例如,排序中的比较操作)
  • 发生某种情况时执行代码(如,点击了一个按钮,数据到达,等等)
  • 只在必要时才运行代码

常见的函数式接口

我们如果也想要编写支持lambda表达式的方法,我们就可以使用函数式接口来完成,不需要自己再去定义接口,下面就会列出一些常见的函数式接口

在这里插入图片描述

下图列出了基本类型int、long和double的34个可用的特殊化接口。使用这些特殊化接口比使用通用接口更高效。这些后面的博客中会进行说明

在这里插入图片描述

自己设计一个支持lambda的方法

我们就使用上面提供的一些函数式接口来设计一个支持lambda的方法
这个方法就使用到了Predicate这个函数式接口,对于这个接口忘了请参考如下

在这里插入图片描述

该接口源代码为

在这里插入图片描述

我们设计的方法如下

public class DesignLambdaMethod {public static <T> List<T> filterList(List<T> list, Predicate<T> predicate) {List<T> tList = new ArrayList<>();for (T t : list) {if (predicate.test(t)) {tList.add(t);}}return tList;}
}

这个方法接收一个List,然后接收一个Predicate,如果Predicate中的test方法返回为真,那么我们就不进行处理,否则就将其移除List。这个方法就可以用于过滤List。
具体使用如下

    public static void main(String[] args) {List<String> list = Arrays.asList("tom", "jack", "ttpfx", "mike", "lc");System.out.println(list);// 要求过滤掉list中的长度小于等于3的字符串List<String> newList = filterList(list, s -> s.length() > 3);System.out.println(newList);}

上面的程序运行后输出如下,成功完成需求

在这里插入图片描述

自定义函数式接口

对于函数式接口的定义想必大家已经很清楚了,只需要在接口有且只有抽象方法就是一个函数式接口。下面就是自定义的一个函数式接口

public interface MyInterface {<R> void apply(R r);
}

对于函数式接口,我们可以使用@FunctionalInterface进行标识。这样做有2个优点,如下

  • 如果你无意中增加了另一个抽象方法,编译器会产生一个错误消息
  • javadoc页里会指出你的接口是一个函数式接口。
@FunctionalInterface
public interface MyInterface {<R> void apply(R r);
}

如果使用@FunctionalInterface后,我们再增加一个抽象方法,那么就会出现以下错误信息

在这里插入图片描述

最后需要说明的是并不是一定要@FunctionalInterface接口,但是建议所有的函数式接口都使用该接口进行标识

总结

相信大家经过上面的讲解,对于lambda应该已经有了些大概的了解。这篇文章是根据我自己对lambda的理解写出的,如果讲解中有错误的地方还请评论区指出,共同提高

相关文章:

【java基础】一篇文章彻底搞懂lambda表达式

文章目录lambda表达式是什么lambda表达式的语法函数式接口初次使用深入理解方法引用 :: 用法快速入门不同形式的::情况1 object::instanceMethod情况2 Class::instanceMethod情况3 Class::staticMethod对于 :: 的一些示例及其注意事项构造器引用变量作用域使用外部变量定义内部…...

通用SQL查询分析器

技术&#xff1a;Java、JSP等摘要&#xff1a;本文主要针对当前很多软件都无法实现跨数据库、跨平台来执行sql语句而用户又仅需做一些基本的增删改查操作的矛盾&#xff0c;设计了一个能够跨平台跨数据库的软件。此软件是一个通用SQL查询分析器&#xff0c;利用java语言本身的跨…...

机器学习100天(三十八):038 朴素贝斯-处理离散数据

《机器学习100天》完整目录:目录 机器学习100天,今天讲的是:朴素贝斯-处理离散数据! 打开 spyder,新建一个 naive_bayes_category.py 脚本。上一节我们引入了一批西瓜样本。并使用朴素贝叶斯公式计算出一个瓜蒂脱落、圆形、青色的西瓜是熟瓜的概率。下面我们来使用 pytho…...

【3.3】指针、二分、SSM项目

二分查找 class Solution {public int search(int[] nums, int target) {int n nums.length;int left 0;int right n - 1;while(left < right){int mid left (right - left) / 2;if(nums[mid] < target){left mid 1;}else if(nums[mid] > target){right mid …...

buu [INSHack2017]rsa16m 1

题目描述&#xff1a; 打开的 rsa_16m 文件 &#xff1a; &#xff08;在此我只想说神人才找得到 c 的位置&#xff09; &#xff0c;这位置是真的难找啊 题目分析&#xff1a; 首先打开 description.md 文件&#xff0c;得到&#xff1a; 翻译下来&#xff1a; 当您需要真正…...

【数据结构起航】:衡量算法的好坏--时间空间复杂度

时间复杂度和空间复杂度 文章目录时间复杂度和空间复杂度1.算法效率1.1算法复杂度1.2复杂度在OJ里的应用2.时间复杂度2.1时间复杂度的概率2.2大O渐进表示法推导大O阶方法&#xff1a;2.3时间复杂度的举例计算3.空间复杂度3.1空间复杂度的举例计算4.复杂度各量级对比1.算法效率 …...

动手学深度学习【1】——线性回归

动手学深度学习网址&#xff1a;动手学深度学习 注&#xff1a;本部分只对基础知识进行简单的介绍并附上完整的代码实现&#xff0c;更多内容可参考上述网址。 简述 需要的准备知识 数学的偏导线性代数 线性模型 回归是能为一个或多个自变量与因变量之间关系建模的一类方…...

Html 相关知识

Html 相关知识 DOM 文档对象模型 (DOM) 是 HTML 和 XML 文档的编程接口。它提供了对文档的结构化的表述&#xff0c;并定义了一种方式可以使从程序中对该结构进行访问&#xff0c;从而改变文档的结构&#xff0c;样式和内容。DOM 将文档解析为一个由节点和对象&#xff08;包…...

【冲刺蓝桥杯的最后30天】day1

大家好&#x1f603;&#xff0c;我是想要慢慢变得优秀的向阳&#x1f31e;同学&#x1f468;‍&#x1f4bb;&#xff0c;断更了整整一年&#xff0c;又开始恢复CSDN更新&#xff0c;从今天开始逐渐恢复更新状态&#xff0c;正在备战蓝桥杯的小伙伴可以支持一下哦&#xff01;…...

c++泛型编程与模板-01函数模板

函数模板的定义 所谓函数模板&#xff0c;实际就是写一个通用函数&#xff0c;返回值和参数的类型都是可变的&#xff0c;用一个特定格式的变量来指定&#xff0c;然后调用此函数的时候&#xff0c;编译器会根据参数的数据类型自动推导出类型&#xff0c;从而达到函数再不同的…...

Golang http请求忘记调用resp.Body.Close()而导致的协程泄漏问题(含面试常见协程泄漏相关测试题)

参考&#xff1a; 知乎&#xff1a;别因为忘记close你的httpclient&#xff0c;造成goroutine泄漏 CSDN&#xff1a;resp.Body.Close() 引发的内存泄漏goroutine个数 先来看几道题&#xff0c;想一想最终的输出结果是多少呢&#xff1f; package mainimport ("fmt"…...

进程信号生命周期详解

信号和信号量半毛钱关系都没有&#xff01; 每个信号都有一个编号和一个宏定义名称,这些宏定义可以在signal.h中找到,例如其中有定 义 #define SIGINT 2 查看信号的机制&#xff0c;如默认处理动作man 7 signal SIGINT的默认处理动作是终止进程&#xff0c;SIGQUIT的默认处理…...

2023-03-03干活小计

今天见识了 归一化的重要性&#xff1a;归一化 不容易爆炸 深度了解了学习率&#xff1a;其实很多操作 最后的结果都是改变了lr 以房价预测为例&#xff1a;一个点一个点更新 比较 矩阵的更新&#xff1a; 为什么小批量梯度下降 优于随机梯度下降 优于批量梯度下降&#xff…...

操作系统结构

随着操作系统的不断增多和代码规模的不断扩大&#xff0c;提供合理的结构对提升操作系统的安全与可靠性来说变得尤为重要。 1.分层法 指将操作系统分为若干层&#xff0c;最低层位硬件&#xff0c;最高层为用户接口&#xff0c;每层只能调用紧邻它的低层的功能和服务(类似于计…...

[SSD科普] 固态硬盘物理接口SATA、M.2、PCIe常见疑问,如何选择?

前言犹记得当年Windows 7系统体验指数中&#xff0c;那5.9分磁盘分数&#xff0c;在其余四项的7.9分面前&#xff0c;似乎已经告诉我们机械硬盘注定被时代淘汰。势如破竹的SSD固态硬盘&#xff0c;彻底打破了温彻斯特结构的机械硬盘多年来在电脑硬件领域的统治。SSD数倍于HDD机…...

【Java学习笔记】3.Java 基础语法

Java 基础语法 一个 Java 程序可以认为是一系列对象的集合&#xff0c;而这些对象通过调用彼此的方法来协同工作。下面简要介绍下类、对象、方法和实例变量的概念。 对象&#xff1a;对象是类的一个实例&#xff0c;有状态和行为。例如&#xff0c;一条狗是一个对象&#xff…...

Python基础学习6——if语句

基本概念 if语句为条件判断语句&#xff0c;用来判断if后面的语句是真是假。if的用途有很多&#xff0c;比如作为条件测试可以判断两数是否相等与不等、进行数值笔记等等。例子如下&#xff1a; Lego_price (599, 799, 898) if Lego_price[0] 599:print("Correct!&quo…...

有免费的PDF转Word吗?值得收藏的7个免费 PDF转Word工具请收好

PDF 和 DOC 是人们在工作中广泛使用的两种最流行的文档格式。PDF 是 Adobe 的便携式文档格式&#xff0c;DOC 是 Microsoft 的 Word 文档格式。PDF 是一种更安全可靠的文件格式&#xff0c;因为它很难编辑 PDF 文件&#xff0c;但是有一些称为 PDF 编辑器的工具可用于编辑 PDF …...

Thinkphp6使用RabbitMQ消息队列

Thinkphp6连接使用RabbitMQ&#xff08;不止tp6&#xff0c;其他框架对应改下也一样&#xff09;&#xff0c;如何使用Docker部署RabbitMQ&#xff0c;在上一篇已经讲了->传送门<-。 部署环境 开始前先进入RabbitMQ的web管理界面&#xff0c;选择Queues菜单&#xff0c;点…...

小成本互联网创业怎么做?低成本创业的方法分享

多数人都会有想法创业&#xff0c;尤其是在互联网上面创业&#xff0c;很多人看到了商机&#xff0c;但是因为成本的原因又放弃了&#xff0c;实际上&#xff0c;小成本也可以互联网创业&#xff01;那么&#xff0c;小成本互联网创业怎么做&#xff1f;低成本创业的方法在这里…...

Leetcode 3576. Transform Array to All Equal Elements

Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接&#xff1a;3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到&#xf…...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用&#xff0c;可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器&#xff0c;能够帮助开发者更好地管理复杂的依赖关系&#xff0c;而 GraphQL 则是一种用于 API 的查询语言&#xff0c;能够提…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!

5月28日&#xff0c;中天合创屋面分布式光伏发电项目顺利并网发电&#xff0c;该项目位于内蒙古自治区鄂尔多斯市乌审旗&#xff0c;项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站&#xff0c;总装机容量为9.96MWp。 项目投运后&#xff0c;每年可节约标煤3670…...

Java 加密常用的各种算法及其选择

在数字化时代&#xff0c;数据安全至关重要&#xff0c;Java 作为广泛应用的编程语言&#xff0c;提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景&#xff0c;有助于开发者在不同的业务需求中做出正确的选择。​ 一、对称加密算法…...

什么是EULA和DPA

文章目录 EULA&#xff08;End User License Agreement&#xff09;DPA&#xff08;Data Protection Agreement&#xff09;一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA&#xff08;End User License Agreement&#xff09; 定义&#xff1a; EULA即…...

【HTTP三个基础问题】

面试官您好&#xff01;HTTP是超文本传输协议&#xff0c;是互联网上客户端和服务器之间传输超文本数据&#xff08;比如文字、图片、音频、视频等&#xff09;的核心协议&#xff0c;当前互联网应用最广泛的版本是HTTP1.1&#xff0c;它基于经典的C/S模型&#xff0c;也就是客…...

企业如何增强终端安全?

在数字化转型加速的今天&#xff0c;企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机&#xff0c;到工厂里的物联网设备、智能传感器&#xff0c;这些终端构成了企业与外部世界连接的 “神经末梢”。然而&#xff0c;随着远程办公的常态化和设备接入的爆炸式…...

Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信

文章目录 Linux C语言网络编程详细入门教程&#xff1a;如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket&#xff08;服务端和客户端都要&#xff09;2. 绑定本地地址和端口&#x…...

《C++ 模板》

目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板&#xff0c;就像一个模具&#xff0c;里面可以将不同类型的材料做成一个形状&#xff0c;其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式&#xff1a;templa…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...