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 都增加了哪些新特性
目录 前言 一、站在开发视角,从 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、Opt…...
八股文打卡day11——计算机网络(11)
面试题:HTTP多个TCP连接怎么实现? 我的回答: 1.HTTP1.0的时候,一个TCP连接只能进行一次请求响应。可以建立多个连接到服务器,这样就可以同时进行多个请求响应,提高传输效率。 2.HTTP1.1推出了持久连接&am…...

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

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

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

支付宝沙箱支付-验签出错之编码集异常
异常信息 invalid-signature 错误 验签出错 错误代码 invalid-signature 错误原因: 验签出错,建议检查签名字符串或签名私钥与应用公钥是否匹配,网关生成的验签字符串为: alipay_sdkalipay-sdk-java-dynamicVersionNo&....官方通用…...

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

在pycharm中jupyter连接上了以后显示无此库,但是确实已经安装好了某个库,使用python可以跑,但是使用ipython就跑不了
今天遇到一个事情,就是用pycharm的jupyter时,连接不上,后来手动连接上了以后,发现环境好像不对。 一般来说,这里会是python3,所以里面的环境也是普通python的环境,并没有我下载的库,…...

C++多态性——(3)动态联编的实现——虚函数
归纳编程学习的感悟, 记录奋斗路上的点滴, 希望能帮到一样刻苦的你! 如有不足欢迎指正! 共同学习交流! 🌎欢迎各位→点赞 👍 收藏⭐ 留言📝 成功的秘诀就在于多努力一次ÿ…...

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#基础知识点可查看:C#学习笔记 - C#基础知识 - C#从入门到放弃 第11节 处…...
[python]项目怎么使用第三方库
要在Python项目中使用第三方库,可以按照以下步骤进行: 安装第三方库:使用pip命令安装要使用的第三方库。例如,要安装requests库,可以运行以下命令: pip install requests导入库文件:在Python项…...

java每日一题——双色球系统(答案及编程思路)
前言: 打好基础,daydayup! 题目:要求如下(同时:红球每个号码不可以相同) 编程思路:1,创建一个可以录入数字的数组;2,生成一个可以随机生成数字的数组…...

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

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

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

爬取涛声网音频
代码展现: 代码详情: 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.…...

如何快速且有效的学习自动化测试?
我写一个学习路线吧: 1.学习python基本语法。 2学习路线图 https://www.processon.com/view/link/64e729486ece22263c3e 学习HTML/CSS下的html、xml、webservice三个教程。 3. 然后下一个python的requests库学习写最简单的网络爬虫。知乎上爬虫教程一大堆。 3是…...

openmmlab大模型实战营01
与环境进行交互——智能体更合适 模型微调常见方式 模型评测 模型部署常见问题你 大语言模型本身不具备最新信息和知识的获取,此时需要搭建包含不同模块的智能体框架 智能体:以大语言模型为核心,进行规划、推理和执行...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

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

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命
在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...
Frozen-Flask :将 Flask 应用“冻结”为静态文件
Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是:将一个 Flask Web 应用生成成纯静态 HTML 文件,从而可以部署到静态网站托管服务上,如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...

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

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

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

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