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

JDK17 - 开发者视角,从 JDK8 ~ JDK17 都增加了哪些新特性

目录

前言

一、站在开发视角,从 JDK8 升级到 JDK17 都有哪些新特性

1.1、JDK8 新特性

1.1.1、Optional 类

a)简介

b)使用方法

c)使用场景

1.2、JDK9 新特性

1.2.1、Optional - ifPresentOrElse 解决 if-else

1.2.2、Optional - or 解决多重 if 嵌套

1.2.3、Optional - orElseThrow 内置异常

1.2.4、集合增强 - 集合静态工厂

1.2.5、集合增强 - takeWhile 方法

1.2.6、集合增强 - dropWhile 方法

1.2.7、接口可以定义私有方法

1.3、JDK10

1.3.1、copyOf 方法

1.4、JDK14 新特性

1.4.1、支持文本块

1.4.2、空指针异常的精确定位

1.4.3、instanceof 类型转换

1.5、JDK16 新特性

1.5.1、toList 方法

1.6、JDK17 新特性

1.6.2、switch 增强


前言


本文只是站在开发者视角,来看看升级哪些咱们程序员常用的功能~

一、站在开发视角,从 JDK8 升级到 JDK17 都有哪些新特性


1.1、JDK8 新特性

1.1.1、Optional 类

a)简介

经过统计,空指针异常是导致 Java 应用程序失败的最常见原因,因此 Google 公司 引入了 Optional 类以检查空值的方式来避免空指针异常,使程序员写出更干净的代码.

Optional 类(Java.util.Optional)是一个容器类,可以保存类型T值,表示这个值存在。或者,也可以只保存 null,表示这个值不存在。也就是说,以前用 null 表示一个值不存在,现在 Optional 就可以更好的表达这个概念,避免空指针异常.

b)使用方法

Java文档中说明:这是一个可以为 null 的容器对象.

  • 如果值存在,则 isPresent() 方法会返回 true,调用 get() 方法就会返回该对象.
  • 如果值不存在,则 isPresent() 方法会返回 false,调用 get() 方法就会抛出空指针异常.
@Data
public class Student {private String name;private Integer age;}

1)创建 Optional 对象案例

  • Optional.of(T t):创建一个 Optional 对象,t 必须不为空.
  • Optional.empty():创建一个空的 Optional 实例.
  • Optional.ofNullable(T t):t 可以为 null.
    public void test1() {//创建一个空的 OptionalOptional<Object> empty = Optional.empty();//创建非空的 OptionalStudent student1 = new Student();Optional<Student> os1 = Optional.of(student1);//创建一个空的 OptionalStudent student2 = null;Optional<Student> os2 = Optional.of(student2);}

2)判断 Optional 容器中是否包含对象

  • boolea isPresent():判断是否包含对象.
  • void ifPresent(Consumer<? super T> consumer): 如果 Optional 中有值,就执行Consumer接口的实现代码,并且该值会作为参数传给它.
    public void test2() {//ifPresent 无参使用: 判断 os1 中是否有值Student student = new Student();Optional<Student> os1 = Optional.of(student);System.out.println(os1.isPresent()); //true//ifPresent 有参使用: 若 student 对象不为空,则对该对象进行赋值,并打印一句话os1.ifPresent(aa -> { //此处的 aa 就代指 studentaa.setName("cyk");aa.setAge(20);System.out.println("个人信息已初始化: " + student);});}

3)获取 Optional 容器的对象

  • T get():如果 Optional 包含值,则返回值,否则抛出异常.
  • T orElse(T other):如果 Optional 包含值就返回,否则返回指定的 other 对象.
  • T orElseGet(Supplier<? extends T> other):如果 Optional 包含值就返回,否则返回由Supplier接口实现提供的对象.
  • T orElseThrow(Supplier<? extends X> exceptionSupplier):如果 Optional 包含值则将其返回,否则抛出由 Supplier 接口实现提供的异常.
    public void test3() throws Exception {//get 获取空对象,报错Student student = null;Optional<Student> os1 = Optional.ofNullable(student);Student student1 = os1.get(); //此处抛出异常: java.util.NoSuchElementException: No value present//如果 student 为空,就返回一个新对象Student student2 = os1.orElse(new Student());//如果 student 为空,就调用我们自己实现的函数Student student3 = os1.orElseGet(() -> new Student());//如果 student 为空,就抛出我们指定的异常os1.orElseThrow(() -> new Exception("自定义异常"));}

4)过滤

  • Optional<T> filter(Predicate<? super <T> predicate):如果值存在,并且这个值匹配给定的 predicate,返回一个Optional用以描述这个值,否则返回一个空的Optional。
    public void test4() {Student student = new Student("cyk", 20);Optional<Student> os1 = Optional.ofNullable(student);os1.filter(aa -> aa.getName().equals("cyk")) //此处 aa 代指 student.ifPresent(result -> System.out.println("ok!"));}

5)映射  

map:入参就是 Optional 中的值,并且具有返回值(返回类型就是Optional 对象中的值类型),如果值才执行函数体,否则返回空的 Optional.

    public void test5() {Student student = new Student("cyk", 20);Optional<Student> os1 = Optional.ofNullable(student);//如果 os1 中存在值,就执行 lambda 表达式,如果不存在值,就返回一个空的 OptionalOptional<Student> result = os1.map(aa -> {aa.setAge(aa.getAge() + 1);return aa;});System.out.println(result); //输出: Optional[Student(name=cyk, age=21)]}

c)使用场景

1)例如当你根据 id 从数据库中获取到用户数据时,如果用户数据不为 null,才能可以将年龄 +1.

    public void test1(Integer id) {//写法一: 原生Userinfo userinfo = userinfoMapper.getUserinfoById(id);if(userinfo != null) {userinfo.setAge(userinfo.getAge() + 1);}//写法二: 使用 Optional 函数式编程,一行搞定Optional.ofNullable(userinfoMapper.getUserinfoById(id)).ifPresent(p -> p.setAge(p.getAge() + 1));}

2)当传入的用户数据需要进行判空抛异常处理时

    public void test2() {Userinfo userinfo = new Userinfo(1, null, 20);//原生if(userinfo == null || isEmpty(userinfo.getUsername())|| isEmpty(userinfo.getAge())) {throw new RuntimeException("用户数据不能为空!");}//用 Optional 改进Optional.ofNullable(userinfo).filter(p -> isEmpty(p.getUsername()) || isEmpty(p.getAge())).orElseThrow(() -> new RuntimeException("用户数据不能为空"));}

3)对象赋值,如果有值,则执行业务逻辑,如果没有值,则返回一个默认的对象.

        Optional.ofNullable(userinfo).map(u -> {//业务逻辑...u.setId(2);u.setUsername("cyk");u.setAge(20);return u;}).orElse(new Userinfo(100, "xxx", 0));

1.2、JDK9 新特性

1.2.1、Optional - ifPresentOrElse 解决 if-else

为了解决 if-else 的判断判空情况,JDK9 增强了 Optional,提供了 ifPresentOrElse.

        Userinfo userinfo = new Userinfo(1, "cyk", 20);//if-elseif(userinfo != null) {System.out.println("hello " + userinfo.getUsername());} else {System.out.println("world");}//ifPresentOrElseOptional.ofNullable(userinfo).ifPresentOrElse(u -> System.out.println("hello " + u.getUsername()),() -> System.out.println("world"));

1.2.2、Optional - or 解决多重 if 嵌套

多重 if 容易导致代码可读性降低,误判引发空指针,并且对于多种if嵌套的情况我还是建议大家提前 return(逻辑更清晰),因此 JDK9 增强 Optional ,提供了 or 方法.

        Userinfo nullinfo = null;//原生if(nullinfo == null) {Userinfo userinfo1 = new Userinfo();userinfo1.setId(1);if(userinfo1 == null) {Userinfo userinfo2 = new Userinfo();userinfo2.setId(2);return userinfo2;}return userinfo1;}//Optional 改进后Optional<Userinfo> or = Optional.ofNullable(nullinfo).or(() -> { // nullinfo 为 null,因此执行此 orUserinfo userinfo1 = new Userinfo();userinfo1.setId(1);return Optional.ofNullable(null); //返回一个空的 Optional}).or(() -> { // 上一个 or 返回的 Optional 中没有值时,执行此 orUserinfo userinfo2 = new Userinfo();userinfo2.setId(2);return Optional.ofNullable(userinfo2);});System.out.println(or); //输出: Optional[Userinfo(id=2, username=null, age=null)]

1.2.3、Optional - orElseThrow 内置异常

Optional.ofNullable(null).orElseThrow();

该方法会抛出Optional的内置异常NoSuchElementException.

1.2.4、集合增强 - 集合静态工厂

  • 此方式创建的集合对象都不允许任何写操作,并且都不能为 null.
  • set/map 不能保证输出顺序和定义的顺序一致.
  • 与 Arrays.asList 创建的 List 不同,Arrays 创建的 List 可以 update不能 add/remove ,而静态工厂创建的完全不能进行写操作.
        //1.创建不可变的 ListList<String> strList = List.of("aaa", "bbb", "ccc");//strList.add("ddd"); //报错: Exception in thread "main" java.lang.UnsupportedOperationException//2.创建一个不可变的 set/mapSet<String> set = Set.of("aaa", "bbb", "ccc");Map<String, String> map1 = Map.of("1", "aaa", "2", "bbb", "3", "ccc");//以上 map 创建方式可能会导致分不清 key value,因此也可以通过以下方式创建Map<String, String> map2 = Map.ofEntries(Map.entry("1", "bbb"), Map.entry("2", "bbb"));//set/map 不能保证输出的顺序和定义 键值对 的顺序一致System.out.println(map1);

1.2.5、集合增强 - takeWhile 方法

takeWhile 用来从前向后遍历,遇到不满足的就结束流,最后返回从前到不满足的截断结果(流对象).

        List<Integer> list = List.of(1, 2, 3, 4, 5, 6, 7);List<Integer> result = list.stream().takeWhile(val -> val < 5).toList();System.out.println(result); //输出: [1, 2, 3, 4]

Ps:如果使用不可修改的Set或者Map 在使用这个方法是要注意 会存在每次输出的结果都是不一样的

1.2.6、集合增强 - dropWhile 方法

takeWhile 用来从前向后删除,遇到不满足的就结束流,最后返回原始流剩下的结果(流对象).

因此,也可以理解为 takeWhile 的补集.

        List<Integer> list = List.of(1, 2, 3, 4, 5, 6, 7);List<Integer> result = list.stream().dropWhile(val -> val < 5).toList();System.out.println(result); //输出: [5, 6, 7]System.out.println(list); //Ps: 这里的删除,不影响 list 中原本的值

Ps:如果使用不可修改的Set或者Map 在使用这个方法和takeWhile一样是要注意;

1.2.7、接口可以定义私有方法

接口可以定义一些私有的方法给 default 方法调用,仅此而已。

1.3、JDK10

1.3.1、copyOf 方法

集合提供了 copyOf 方法,返回的不可以修改的集合(修改就抛异常).

Ps:这里使用的深拷贝,因此修改原集合不会影响副本.

        List<String> srcList = new ArrayList<>();srcList.add("aaa");srcList.add("bbb");List<String> copyList = List.copyOf(srcList);srcList.add("ccc");System.out.println(srcList); //[aaa, bbb, ccc]System.out.println(copyList);//[aaa, bbb]

1.4、JDK14 新特性

1.4.1、支持文本块

文本代码块让整个String看上去都是比较整洁的,并且无需进行繁琐的转义.

        //原始String before = "{\n" +"     \"name\":\"cyk\",\n" +"     \"age\": 20;\n" +"}";//增强String after = """{"name": "cyk","age": 20}""";

1.4.2、空指针异常的精确定位

不光可以定义是哪行代码空指针异常,还能定位到调用到哪个方法/属性出现的异常.

//Before:Exception in thread "main" java.lang.NullPointerExceptionat com.dev.wizard.feature.JDK17Demo.optionalMethod_orElseThrow(JDK17Demo.java:99)at com.dev.wizard.feature.JDK17Demo.main(JDK17Demo.java:23)//After:Exception in thread "main" java.lang.NullPointerException: Cannot read field "student" because "persons" is nullat com.dev.wizard.feature.JDK17Demo.optionalMethod_orElseThrow(JDK17Demo.java:99)at com.dev.wizard.feature.JDK17Demo.main(JDK17Demo.java:23)

1.4.3、instanceof 类型转换

以往 instanceof 只能帮我们检查数据类型是否符合,JDK14 中不仅可以进行类型匹配,还会将匹配到的类型直接赋值新的引用,简化了开发,提高了可读性.

        Object val = "aaa";//beforeif(val instanceof String) {String newVal = (String) val;System.out.println(newVal);}//afterif(val instanceof String newVal) {System.out.println(newVal);}

1.5、JDK16 新特性

1.5.1、toList 方法

stream().toList 和 Collectors.toUnmodifiableList()都是不可修改的集合,Collectors.toList()是生成的是普通的list,可写。

性能比较:toList(优) --> Collectors.toList() --> Collectors.toUnmodifiableList(劣)

        List<String> list1 = List.of("aaa", "bbb");//可读可写List<String> list2 = list1.stream().toList();//可读,不可写List<String> list3 = list2.stream().collect(Collectors.toList());List<String> list4 = list1.stream().collect(Collectors.toUnmodifiableList());

1.6、JDK17 新特性

1.6.2、switch 增强

JDK17 中的 switch 主要是使用 -> 替代了 break 语句,看上去更加简洁.

看上去 switch 是想替代 if-else 的感觉~

1)字符串匹配

        //1.字符串匹配String val1 = "aaa";//beforeswitch (val1) {case "abc":System.out.println("abc!");break;case "aaa":System.out.println("aaa!");break;default:System.out.println("error!");}//afterswitch (val1) {case "abc" -> System.out.println("abc!");case "aaa" -> System.out.println("aaa");default -> System.out.println("error");}

2)类型判断

        //2.类型判断Object val2 = "aaa";//beforeif(val2 instanceof String) {String newVal = (String) val2;System.out.println("String:" + newVal);} else if(val2 instanceof Integer) {Integer newVal = (Integer) val2;System.out.println("Integer:" + newVal);} else {System.out.println(val2);}//afterswitch (val2) {case String str -> {String newVal = str;System.out.println("String:" + newVal);}case Integer num -> {Integer newVal = num;System.out.println("Integer:" + newVal);}default -> System.out.println(val2);}

 3)对 null 的处理

        //3.对 null 的处理String val3 = null;switch (val3) {case null -> System.out.println("null!");case "aaa" -> System.out.println("aaa!");case "bbb" -> System.out.println("bbb!");default -> System.out.println("error");}

4)对条件判断的处理

        //4.对条件判断的处理Object obj = 1;switch (obj) {case String str -> {String newVal = str;System.out.println("String:" + newVal);}case Integer num && num < 3 -> {Integer newVal = num;System.out.println("Integer:" + newVal);}default -> System.out.println("error!");}

相关文章:

JDK17 - 开发者视角,从 JDK8 ~ JDK17 都增加了哪些新特性

目录 前言 一、站在开发视角&#xff0c;从 JDK8 升级到 JDK17 都有哪些新特性 1.1、JDK8 新特性 1.1.1、Optional 类 a&#xff09;简介 b&#xff09;使用方法 c&#xff09;使用场景 1.2、JDK9 新特性 1.2.1、Optional - ifPresentOrElse 解决 if-else 1.2.2、Opt…...

八股文打卡day11——计算机网络(11)

面试题&#xff1a;HTTP多个TCP连接怎么实现&#xff1f; 我的回答&#xff1a; 1.HTTP1.0的时候&#xff0c;一个TCP连接只能进行一次请求响应。可以建立多个连接到服务器&#xff0c;这样就可以同时进行多个请求响应&#xff0c;提高传输效率。 2.HTTP1.1推出了持久连接&am…...

在Android设备上设置和使用隧道代理HTTP

随着互联网的深入发展&#xff0c;网络信息的传递已经成为人们日常生活中不可或缺的一部分。对于我们中国人来说&#xff0c;由于某些特殊的原因&#xff0c;访问国外网站时常常会遇到限制。为了解决这个问题&#xff0c;使用代理服务器成为了许多人的选择。而在Android设备上设…...

Paddle3D 2 雷达点云CenterPoint模型训练

2 Paddle3D 雷达点云CenterPoint模型训练–包含KITTI格式数据地址 2.0 数据集 百度DAIR-V2X开源路侧数据转kitti格式。 2.0.1 DAIR-V2X-I\velodyne中pcd格式的数据转为bin格式 参考源码&#xff1a;雷达点云数据.pcd格式转.bin格式 def pcd2bin():import numpy as npimport…...

RabbitMQ集群的简单说明

1.普通集群(副本集群) 当集群中某一时刻master主节点宕机&#xff0c;可以对master中Queue中的消息进行备份。而就算master宕机了&#xff0c;从节点不会对外提供服务&#xff0c;等到master节点恢复后&#xff0c;系统才会恢复正常。 主从架构的缺点是队列中的消息只是位于主节…...

支付宝沙箱支付-验签出错之编码集异常

异常信息 invalid-signature 错误 验签出错 错误代码 invalid-signature 错误原因: 验签出错&#xff0c;建议检查签名字符串或签名私钥与应用公钥是否匹配&#xff0c;网关生成的验签字符串为&#xff1a; alipay_sdkalipay-sdk-java-dynamicVersionNo&amp....官方通用…...

图像分割-漫水填充法 floodFill (C#)

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 本文的VB版本请访问&#xff1a;图像分割-漫水填充法 floodFill-CSDN博客 FloodFill方法是一种图像处理算法&#xff0c;它的目的是…...

在pycharm中jupyter连接上了以后显示无此库,但是确实已经安装好了某个库,使用python可以跑,但是使用ipython就跑不了

今天遇到一个事情&#xff0c;就是用pycharm的jupyter时&#xff0c;连接不上&#xff0c;后来手动连接上了以后&#xff0c;发现环境好像不对。 一般来说&#xff0c;这里会是python3&#xff0c;所以里面的环境也是普通python的环境&#xff0c;并没有我下载的库&#xff0c;…...

C++多态性——(3)动态联编的实现——虚函数

归纳编程学习的感悟&#xff0c; 记录奋斗路上的点滴&#xff0c; 希望能帮到一样刻苦的你&#xff01; 如有不足欢迎指正&#xff01; 共同学习交流&#xff01; &#x1f30e;欢迎各位→点赞 &#x1f44d; 收藏⭐ 留言​&#x1f4dd; 成功的秘诀就在于多努力一次&#xff…...

docker部署mysql

1.查找mysql镜像 [rootVM-4-5-centos ~]# docker search mysql NAME DESCRIPTION STARS OFFICIAL AUTOMATED mysql MySQL is a widely used, open-sourc…...

python代码大全(持续更新)

读写文件 # 读取文件 with open(file.txt, r) as file:content file.read()# 写入文件 with open(file.txt, w) as file:file.write(Hello, World!)HTTP请求 import requestsresponse requests.get(https://api.example.com/data) data response.json()JSON处理 import j…...

C#学习笔记 - C#基础知识 - C#从入门到放弃 - C# 处理程序异常相关技术

C# 入门基础知识 - C# 处理程序异常相关技术 第11节 处理程序异常相关技术11.1 捕获异常11.2 清除、处理所有异常11.3 引发异常11.4 预定义异常类11.5 自定义异常类11.6 异常的综合运用 更多C#基础知识点可查看&#xff1a;C#学习笔记 - C#基础知识 - C#从入门到放弃 第11节 处…...

[python]项目怎么使用第三方库

要在Python项目中使用第三方库&#xff0c;可以按照以下步骤进行&#xff1a; 安装第三方库&#xff1a;使用pip命令安装要使用的第三方库。例如&#xff0c;要安装requests库&#xff0c;可以运行以下命令&#xff1a; pip install requests导入库文件&#xff1a;在Python项…...

java每日一题——双色球系统(答案及编程思路)

前言&#xff1a; 打好基础&#xff0c;daydayup! 题目&#xff1a;要求如下&#xff08;同时&#xff1a;红球每个号码不可以相同&#xff09; 编程思路&#xff1a;1&#xff0c;创建一个可以录入数字的数组&#xff1b;2&#xff0c;生成一个可以随机生成数字的数组&#xf…...

java的mybatis

一.spring 整合单元测试 二.lombok 三.注解方式开发 四.xml 方式开发 五.动态sql...

Linux驱动开发简易流程

推荐视频&#xff1a; 正点原子【第四期】手把手教你学 Linux之驱动开发篇 小智-学长嵌入式Linux&Android底层开发入门教程 能力矩阵 基础能力矩阵 熟悉c/c、熟悉数据结构 熟悉linux系统&#xff0c;Shell脚本&#xff0c;Makefile/cmake/mk 文件IO、多线程、竞争、并发…...

基于springboot的靓车汽车销售网站

&#x1f345;点赞收藏关注 → 私信领取本源代码、数据库&#x1f345; 本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目希望你能有所收获&#xff0c;少走一些弯路。&#x1f345;关注我不迷路&#x1f345;一 、设计说明 1.1 研究背景 随…...

爬取涛声网音频

代码展现&#xff1a; 代码详情&#xff1a; import requests import re import os filename 声音// if not os.path.exists(filename): os.mkdir(filename) def down_load(page): for page in range(page): page page1 url https://www.tosound.…...

如何快速且有效的学习自动化测试?

我写一个学习路线吧&#xff1a; 1.学习python基本语法。 2学习路线图 https://www.processon.com/view/link/64e729486ece22263c3e 学习HTML/CSS下的html、xml、webservice三个教程。 3. 然后下一个python的requests库学习写最简单的网络爬虫。知乎上爬虫教程一大堆。 3是…...

openmmlab大模型实战营01

与环境进行交互——智能体更合适 模型微调常见方式 模型评测 模型部署常见问题你 大语言模型本身不具备最新信息和知识的获取&#xff0c;此时需要搭建包含不同模块的智能体框架 智能体&#xff1a;以大语言模型为核心&#xff0c;进行规划、推理和执行...

生成xcframework

打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式&#xff0c;可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

【杂谈】-递归进化:人工智能的自我改进与监管挑战

递归进化&#xff1a;人工智能的自我改进与监管挑战 文章目录 递归进化&#xff1a;人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管&#xff1f;3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

如何在看板中有效管理突发紧急任务

在看板中有效管理突发紧急任务需要&#xff1a;设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP&#xff08;Work-in-Progress&#xff09;弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中&#xff0c;设立专门的紧急任务通道尤为重要&#xff0c;这能…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命

在华东塑料包装行业面临限塑令深度调整的背景下&#xff0c;江苏艾立泰以一场跨国资源接力的创新实践&#xff0c;重新定义了绿色供应链的边界。 跨国回收网络&#xff1a;废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点&#xff0c;将海外废弃包装箱通过标准…...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是&#xff1a;将一个 Flask Web 应用生成成纯静态 HTML 文件&#xff0c;从而可以部署到静态网站托管服务上&#xff0c;如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

Python爬虫(一):爬虫伪装

一、网站防爬机制概述 在当今互联网环境中&#xff0c;具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类&#xff1a; 身份验证机制&#xff1a;直接将未经授权的爬虫阻挡在外反爬技术体系&#xff1a;通过各种技术手段增加爬虫获取数据的难度…...

使用SSE解决获取状态不一致问题

使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件&#xff0c;这个上传文件是整体功能的一部分&#xff0c;文件在上传的过程中…...

Matlab实现任意伪彩色图像可视化显示

Matlab实现任意伪彩色图像可视化显示 1、灰度原始图像2、RGB彩色原始图像 在科研研究中&#xff0c;如何展示好看的实验结果图像非常重要&#xff01;&#xff01;&#xff01; 1、灰度原始图像 灰度图像每个像素点只有一个数值&#xff0c;代表该点的​​亮度&#xff08;或…...

JDK 17 序列化是怎么回事

如何序列化&#xff1f;其实很简单&#xff0c;就是根据每个类型&#xff0c;用工厂类调用。逐个完成。 没什么漂亮的代码&#xff0c;只有有效、稳定的代码。 代码中调用toJson toJson 代码 mapper.writeValueAsString ObjectMapper DefaultSerializerProvider 一堆实…...