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!");}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/229873.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

泄放电路与LDO扩流电路

直接用并联电阻的方式进行能量泄放&#xff0c;这种方式简单直接但是电阻会损耗掉一定能量&#xff1a; 安规电容旁边的电阻&#xff1a; 2.三极管泄放电路&#xff1a;针对于大功率场景电阻不便于直接使用的时候&#xff0c;主要目的是电源断开时泄放大电容C1的能量。利用了三…

CNN——LeNet

1.LeNet概述 LeNet是Yann LeCun于1988年提出的用于手写体数字识别的网络结构&#xff0c;它是最早发布的卷积神经网络之一&#xff0c;可以说LeNet是深度CNN网络的基石。 当时&#xff0c;LeNet取得了与支持向量机&#xff08;support vector machines&#xff09;性能相…

软件测试之白盒测试

概念与定义 白盒测试&#xff1a;侧重于系统或部件内部机制的测试&#xff0c;类型分为分支测试&#xff08;判定节点测试&#xff09;、路径测试、语句测试。 控制流分析(基于程序结构)&#xff1a;控制流分析是一类用于分析程序控制流结构的静态分析技术&#xff0c;目的在于…

约束满足问题改进技术:基于变量和赋值次序的启发式

回溯搜索的通用算法的问题与改进思路 • 需改善无信息回溯搜索算法的性能。 • 通用改进方法的思路&#xff1a; – 下一步该给哪个变量赋值&#xff0c; 按什么顺序给该变量赋值&#xff1f; – 每步搜索应该做怎样的推理&#xff1f; 当前变量的赋值会对其他未赋值变量产…

【SpringBoot框架篇】34.使用Spring Retry完成任务的重试

文章目录 简要1.为什么需要重试&#xff1f;2.添加maven依赖3.使用Retryable注解实现重试4.基于RetryTemplate模板实现重试 简要 Spring实现了一套重试机制&#xff0c;功能简单实用。Spring Retry是从Spring Batch独立出来的一个功能&#xff0c;已经广泛应用于Spring Batch,…

算法巡练day04Leetcode24交换节点19删除倒数节点142环形链表

今天学习的文章和视频链接 https://www.bilibili.com/video/BV1YT411g7br/?vd_source8272bd48fee17396a4a1746c256ab0ae https://www.bilibili.com/video/BV1if4y1d7ob/?vd_source8272bd48fee17396a4a1746c256ab0ae 24两两交换链表中的节点 给你一个链表&#xff0c;两两…

ASP.NET Core基础之图片文件(一)-WebApi图片文件上传到文件夹

阅读本文你的收获&#xff1a; 了解WebApi项目保存上传图片的三种方式学习在WebApi项目中如何上传图片到指定文件夹中 在ASP.NET Core基础之图片文件(一)-WebApi访问静态图片文章中&#xff0c;学习了如何获取WebApi中的静态图片&#xff0c;本文继续分享如何上传图片。 那么…

八皇后问题(C语言/C++)超详细讲解/由浅入深---深入八皇后问题

介绍引入 在计算机科学中&#xff0c;八皇后问题是一个经典的回溯算法问题。这个问题的目标是找出一种在8x8国际象棋棋盘上放置八个皇后的方法&#xff0c;使得没有任何两个皇后能够互相攻击。换句话说&#xff0c;每一行、每一列以及对角线上只能有一个皇后。 想象一下&…

为什么大学c语言课不顺便教一下Linux,Makefile

为什么大学c语言课不顺便教一下Linux&#xff0c;Makefile&#xff0c;git&#xff0c;gdb等配套工具链呢? 在开始前我有一些资料&#xff0c;是我根据自己从业十年经验&#xff0c;熬夜搞了几个通宵&#xff0c;精心整理了一份「Linux的资料从专业入门到高级教程工具包」&…

Docker 网络管理

一、Docker网络简介 Docker网络是容器化应用程序的重要组成部分&#xff0c;它使得容器之间可以互相通信和连接&#xff0c;同时也提供了容器与外部环境之间的隔离和连接。 二、Docker网络网络模式 Docker 提供了多种网络模式&#xff0c;可以通过docker network ls 命令查看…

MySQL——事物

目录 一.发现问题 二.什么时事物 三.事务提交方式 四.事物的常规操作方式 五. 事务隔离级别 1.如何理解隔离性 2.隔离级别 3.查看与设置隔离性 4.读未提交【Read Uncommitted】 5.读提交【Read Committed】 6.可重复读【Repeatable Read】 7.串行化【serializabl…

Unity游戏资源更新(AB包)

目录 前言&#xff1a; 一、什么是AssetBundle 二、AssetBudle的基本使用 1.AssetBundle打包 2.BuildAssetBundle BuildAssetBundleOptions BuildTarget 示例 3.AssetBundle的加载 LoadFromFile LoadFromMemory LoadFromMemoryAsync UnityWebRequestAsssetBundle 前…

QProgressDialog用法及结合QThread用法,四种线程使用

1 QProgressDialog概述 QProgressDialog类提供耗时操作的进度条。 进度对话框用于向用户指示操作将花费多长时间&#xff0c;并演示应用程序没有冻结。此外&#xff0c;QPorgressDialog还可以给用户一个中止操作的机会。 进度对话框的一个常见问题是很难知道何时使用它们;操作…

Linux shell编程学习笔记38:history命令

目录 0 前言 1 history命令的功能、格式和退出状态1.1 history命令的功能1.2 history命令的格式1.3退出状态2 命令应用实例2.1 history&#xff1a;显示命令历史列表2.2 history -a&#xff1a;将当前会话的命令行历史追加到历史文件~/.bash_history中2.3 history -c&#xf…

如何做好档案数字化前的鉴定工作

要做好档案数字化前的鉴定工作&#xff0c;可以按照以下步骤进行&#xff1a; 1. 确定鉴定目标&#xff1a;明确要鉴定的档案的内容、数量和性质&#xff0c;确定鉴定的范围和目标。 2. 进行档案清点&#xff1a;对档案进行全面清点和登记&#xff0c;包括数量、种类、状况等信…

【Linux】基本指令了解(一)

&#x1f497;个人主页&#x1f497; ⭐个人专栏——数据结构学习⭐ &#x1f4ab;点击关注&#x1f929;一起学习C语言&#x1f4af;&#x1f4ab; 目录 导读&#xff1a;1. 认识Linux1.1 什么是Linux1.2 Linux特点 2. ls指令3. pwd命令4. cd 指令5. touch命令6. mkdir指令7. …

<JavaEE> TCP 的通信机制(二) -- 连接管理(三次握手和四次挥手)

目录 TCP的通信机制的核心特性 三、连接管理 1&#xff09;什么是连接管理&#xff1f; 2&#xff09;“三次握手”建立连接 1> 什么是“三次握手”&#xff1f; 2> “三次握手”的核心作用是什么&#xff1f; 3&#xff09;“四次挥手”断开连接 1> 什么是“…

听GPT 讲Rust源代码--library/panic_unwind

File: rust/library/panic_unwind/src/seh.rs 在Rust源代码中&#xff0c;rust/library/panic_unwind/src/seh.rs这个文件的作用是实现Windows操作系统上的SEH&#xff08;Structured Exception Handling&#xff09;异常处理机制。 SEH是Windows上的一种异常处理机制&#xff…

Mysql 动态链接库配置步骤+ 完成封装init和close接口

1、创建新项目 动态链接库dll 2、将附带的文件都删除&#xff0c;创建LXMysql.cpp 3、项目设置 3.1、预编译头&#xff0c;不使用预编译头 3.2、添加头文件 3.3、添加类 3.4、写初始化函数 4、项目配置 4.1、右键解决方案-属性-常规-输出目录 ..\..\bin 4.2、生成lib文件 右…

3D视觉-相机选用的原则

鉴于不同技术方案都有其适用的场景&#xff0c;立体相机的选型讲究的原则为“先看用途&#xff0c;再看场景&#xff0c;终评精度”&#xff0c;合适的立体相机在方案中可以起到事半功倍的效果。从用途上来进行划分&#xff0c;三维视觉方案主要应用在两个方向&#xff1a;测量…