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.mzph.cn/news/593958.shtml

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

相关文章

Java程序设计阶段测试1

一、单选题&#xff08;共15题&#xff1b; 共30.0分&#xff09; 2.0分 1、以下哪个是Java应用程序main方法的有效定义? A.public static void main(); B.public static void main( String args ); C.public static void main( String args[] ); D.public static boolea…

Go Lang Fiber介绍

利用GoLang Fiber进行高性能Web开发 在不断发展的Web开发世界中&#xff0c;选择合适的框架至关重要。速度、简洁性和强大的功能集是每个开发者都追求的品质。在使用Go构建Web应用时&#xff0c;“Fiber”作为一个强大且轻量级的框架在众多选择中脱颖而出。在这份全面的指南中…

扩展:键盘录入笔记(next()、nextLine()、nextInt()、nextDouble())

文章目录 一&#xff0c;键盘录入涉及到的方法如下&#xff1a;1&#xff09;next&#xff08;&#xff09;、nextLine&#xff08;&#xff09;&#xff1a;代码示例&#xff1a;代码示例&#xff1a; 2&#xff09;nextInt&#xff08;&#xff09;&#xff1a;代码示例&…

无辅源电压继电器 RWY-D2/3 180-440VAC 导轨安装 josef约瑟

RWY-D1型电压继电器&#xff1b; RWY-D2型电压继电器&#xff1b; 一、 概述 RWY-D系列电压继电器&#xff08;以下简称本继电器&#xff09;用于发电机、变压器和输电线的电器保护装置中&#xff0c;作为过电压保护或低电压闭锁的启动原件。本继电器为集成电路静态型继电器…

设计模式--适配器模式

适配器模式 适配器模式&#xff08;Adapter&#xff09;&#xff0c;将一个类的接口转换为客户希望的另一个接口&#xff0c;Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。 系统的数据和行为都正确&#xff0c;但接口不符合时&#xff0c;我们应该…

Python入门学习篇(十七)——封装、继承、多态

1 封装 1.1 理解 属性和方法书写到类里面的操作即为封装 封装可以理解成私有化属性和私有化方法1.2 示例代码 class Person():p_num 0 # 用于统计数量def __init__(self, name, age, sex, job):# __name为私有化属性self.__name nameself.age ageself.sex sexself.job …

使用anaconda创建爬虫spyder工程

1.由于每个工程使用的环境都可能不一样&#xff0c;因此一个好的习惯就是不同的工程都创建属于自己的环境&#xff0c;在anaconda中默认的环境是base&#xff0c;我们现在来创建一个名为spyder的环境&#xff0c;专门用于爬虫工程&#xff1a; //括号中名字&#xff0c;代表当…

森林火灾数据集

野外火灾是全球范围内最致命和危险的天然灾害之一。它不仅对人类的生命安全构成严重威胁&#xff0c;还对动植物的生存环境造成巨大的破坏。预测火灾行为不仅可以帮助消防员更好地应对火情&#xff0c;还可以为未来的火灾预防和应对策略提供有力支持。 随着航空图像技术的不断…

Windows可以ping通ubuntu,但ubuntu无法ping通windows

使用了NAT网卡和桥接网卡&#xff0c;电脑连了WiFi&#xff0c;桥接网卡桥接到WLAN上&#xff0c;Windows可以ping通Ubuntu但反过来不行&#xff01; 1.可能是防火墙的问题&#xff0c;按照如下设置&#xff0c;无果 考虑是不是使用了两个网卡冲突了&#xff0c;取消NAT的链接 …

【笔记】书生·浦语大模型实战营——第一课

群公告 1月3日*更新 第一次课程视频链接&#xff1a;https://www.bilibili.com/video/BV1Rc411b7ns/&#xff0c;第一次课程只需要记笔记&#xff0c;没有作业。第一次课程(1月3日)和第二次课程(1月5日)到本周末(1月7日)截止&#xff0c;笔记记录在 知乎/CSDN/Github 或者任何你…

【操作系统xv6】学习记录--实验1 Lab: Xv6 and Unix utilities--未完

ref:https://pdos.csail.mit.edu/6.828/2020/xv6.html 实验&#xff1a;Lab: Xv6 and Unix utilities 环境搭建 实验环境搭建&#xff1a;https://blog.csdn.net/qq_45512097/article/details/126741793 搭建了1天&#xff0c;大家自求多福吧&#xff0c;哎。~搞环境真是折磨…

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

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

Document对象详解

前言 在前端开发中&#xff0c;DOM&#xff08;文档对象模型&#xff09;扮演着重要的角色。它允许我们使用JavaScript来与网页文档进行交互&#xff0c;实现动态的网页效果。DOM的核心部分之一就是Document对象&#xff0c;它代表了整个HTML文档。在本篇博客中&#xff0c;我们…

华媒舍:6个使你的媒体发稿推广更简单的方法!

做为新闻报道媒体从业人员&#xff0c;在宣传发稿上要行走在最前沿&#xff0c;保持竞争力。下面我们就向您介绍六个又简单又实用的方法&#xff0c;帮助你提升新闻报道媒体营销推广发稿效果。 方法一&#xff1a;明确目标群体我们应该明确定义我们自己的目标群体。掌握观众的特…

小H靶场笔记:DC-3

DC-3 January 3, 2024 4:11 PM Tags&#xff1a;Joomla owner&#xff1a;只惠摸鱼 信息收集 探测靶机ip&#xff1a; 192.168.199.133 nmap 扫描端口、 系统版本 漏洞 发现只有80端口开发&#xff0c; 且有cve-2017-8917漏洞存在是Joomla的SQL注入漏洞 Joomla版本为3.7.0…

相关性与P值

相关性与P值 0 FQA&#xff1a;1 相关性与显著性的关系2 相关性分析3 使用medcalc进行相关性分析&#xff1a;参考文章&#xff1a; 0 FQA&#xff1a; 主要描述相关性和p值分别代表什么意义&#xff1f; 以及如何使用medcalc计算相关性和p值。 Q1&#xff1a;p值代表什么意义…

【每日一题】466. 统计重复个数-2024.1.2

题目&#xff1a; 466. 统计重复个数 定义 str [s, n] 表示 str 由 n 个字符串 s 连接构成。 例如&#xff0c;str ["abc", 3] "abcabcabc" 。 如果可以从 s2 中删除某些字符使其变为 s1&#xff0c;则称字符串 s1 可以从字符串 s2 获得。 例如&…

主流桌面浏览器Chrome,FireFox和Edge等如何禁用弹出式窗口阻止程序,这里有详细步骤

为什么你想知道如何禁用浏览器中的弹出式窗口阻止程序?毕竟,弹出式窗口是网络的祸害:显示烦人的广告、虚假的安全消息和其他刺激,会分散你的浏览注意力,甚至可能包含恶意代码。 所有主要的桌面浏览器现在都默认阻止弹出式窗口,那么你到底为什么要取消阻止这些害虫呢?事…

【力扣100】39.组合总和

添加链接描述 class Solution:def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:def backtrack(path,target,res,index):if target0:res.append(path[:])returnif target<0:return for i in range(index,len(candidates)):if target&g…

c盘扩容时,d盘无法删除卷问题

C盘扩容时&#xff0c;磁盘管理中D盘右键无法删除卷的原因 首先&#xff0c;D盘下文件夹为空&#xff0c;但是显示可用空间不是100%&#xff0c;经过排查&#xff0c;发现是虚拟内存设置在了D盘导致无法删除卷&#xff0c;这里只需要将虚拟内存放到其他盘&#xff0c;如E盘即可…