如果您想比较不同版本的 Java API,有一个很棒的工具Java Version Almanac。

我们跳过中间的版本直接对比Java8和Java17和我们开发有关的差异。

Java 17 特性

  • 1. Java 17 与 Java 8:变化
  • 2. 扩展switch表达式
  • 2. 实例匹配
  • 3. 密封类(Sealed Classes)
  • 4. 文本块
  • 5. 新的 Optional.orElseThrow() 方法
  • 6. 其他小而精的 API 更改
  • 7. 垃圾收集器
  • 8. 容器意识
  • 9. CDS档案
  • 10. Java Flight Recorder 和 Java Mission Control
  • 11. 你应该从 Java 8 迁移到 Java 17 吗?
  • 小结

1. Java 17 与 Java 8:变化

添加了一个新的var关键字,允许以更简洁的方式声明局部变量。

// java 8
Map<String, List<MyDtoType>> myMap = new HashMap<String, List<MyDtoType>>();
List<MyDomainObjectWithLongName> myList = aDelegate.fetchDomainObjects();// java 10
var myMap = new HashMap<String, List<MyDtoType>>();
var myList = aDelegate.fetchDomainObjects()

我们不能使用var 关键字接收 lambda 的值:

var  fun  =  MyObject :: mySpecialFunction;
// 导致编译错误:(方法引用需要明确的目标类型)

但是,可以在 lambda 表达式中可以使用var

boolean isThereAneedle = stringsList.stream().anyMatch((@NonNull var s) -> s.equals(“needle”));

2. 扩展switch表达式

java17的switch case 可以更容易地以更易读的方式分组(注意没有break!)。

DayOfWeek dayOfWeek = LocalDate.now().getDayOfWeek();
boolean freeDay = switch (dayOfWeek) {case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> false;case SATURDAY, SUNDAY -> true;
};

还允许从代码块内部返回值的yield 关键字,它实际上是一个从 case 块内部工作的返回 值,并通过其switch设置该值。

DayOfWeek dayOfWeek = LocalDate.now().getDayOfWeek();
boolean freeDay = switch (dayOfWeek) {case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> {System.out.println("Work work work");yield false;}case SATURDAY, SUNDAY -> {System.out.println("Yey, a free day!");yield true;}
};

2. 实例匹配

java8时, 我们通常会写这样的代码

if (obj instanceof MyObject) {MyObject myObject = (MyObject) obj;// TODO
}

Java 现在可以在if 中创建一个局部变量, 它将替我们进行强转。

if (obj instanceof MyObject myObject) {// TODO
}

此外,声明的变量可以在if 条件中使用

if (obj instanceof MyObject myObject && myObject.isValid()) {// TODO
}

3. 密封类(Sealed Classes)

在switch 中的“no default”警告有没有让你烦恼?您涵盖了域接受的所有选项,但警告仍然存在。使用密封类就可以摆脱对instanceof 类型检查的警告的烦恼。

public abstract sealed class Animal permits Dog, Cat {}public final class Dog extends Animal {}public final class Cat extends Animal {}// 你可以这样获取他们而不用强迫症的写上else的默认结果。
if (animal instanceof Dog d) {return d.woof();
} else if (animal instanceof Cat c) {return c.meow();
}

4. 文本块

String myWallOfText = """
______         _   _
| ___ \       | | (_)
| |_/ / __ ___| |_ _ _   _ ___
|  __/ '__/ _ \ __| | | | / __|
| |  | | |  __/ |_| | |_| \__ \
\_|  |_|  \___|\__|_|\__,_|___/
"""

可以转义换行符并将字符串保持为单行

String text = """
又是写bug的一天, \
又是加班的一天。
"""

这相当于

String text = "又是写bug的一天,又是加班的一天"。

文本块可用于在您的代码中保留合理可读的 JSON 或 XML 模板。

5. 新的 Optional.orElseThrow() 方法

MyObject myObject = myList.stream().filter(MyObject::someBoolean).filter((b) -> false).findFirst().get();

在get不到对象时,该方法会抛出异常。Java 10 在 Optional 中引入了一个新方法orElseThrow(),感觉没什么用处,get不到还是要抛出异常。但是考虑到程序的可读性,写上瞬间有点严谨的感觉。

MyObject myObject = myList.stream()
.filter(MyObject::someBoolean)
.filter((b) -> false)
.findFirst()
.orElseThrow();

6. 其他小而精的 API 更改

// invert a Predicate, will be even shorter with static import
collection.stream().filter(Predicate.not(MyObject::isEmpty)).collect(Collectors.toList());// String got some new stuff too
“\nPretius\n rules\n  all!”.repeat(10).lines()..filter(Predictions.not(String::isBlank)).map(String::strip).map(s -> s.indent(2)).collect(Collectors.toList());// no need to have an instance of array passed as an argument
String[] myArray= aList.toArray(String[]::new);// read and write to files quickly!
// remember to catch all the possible exceptions though
Path path = Files.writeString(myFile, "Pretius Rules All !");
String fileContent = Files.readString(path);// .toList() on a stream()
String[] arr={"a", "b", "c"};
var list = Arrays.stream(arr).toList();

7. 垃圾收集器

从 Java 9 开始,G1 是默认的垃圾收集器。与 Parallel GC 相比,它减少了暂停时间,尽管它的总体吞吐量可能较低。G1的更新包括将未使用的已提交内存返回给操作系统的能力(JEP 346)。

ZGC 垃圾收集器已在 Java 11 中引入,并已在 Java 15 ( JEP 377 ) 中达到产品状态。它旨在进一步减少停顿。从 Java 13 开始,它也可以将未使用的已提交内存返回给操作系统 ( JEP 351 )。

JDK 14 中引入了 Shenandoah GC,并在 Java 15 ( JEP 379 ) 中达到了产品状态。它旨在保持低暂停时间并独立于堆大小。

更多的GC了解请转https://jet-start.sh/blog/2020/06/09/jdk-gc-benchmarks-part1。

在 Java 8 中如果您没有手动更改 GC,您仍然使用Parallel GC。简单地切换到 Java 17 可能会使您的应用程序运行得更快,并具有更一致的方法运行时间。切换到 ZGC 或 Shenandoah 可能会得到更好的结果。

最后,No-Op Garbage Collector(JEP 318),尽管它是一个实验性功能。这个垃圾收集器实际上不做任何工作,因此允许您精确测量应用程序的内存使用情况。如果您想保持尽可能低的内存操作吞吐量,则很有用。

8. 容器意识

Java 曾有一段时间不知道它正在容器中运行。它没有考虑容器的内存限制,而是读取可用的系统内存。因此,当您有一台具有 16 GB RAM 的机器,将容器的最大内存设置为 1 GB,并在其上运行 Java 应用程序时,该应用程序通常会失败,因为它会尝试分配比可用内存更多的内存容器。从 Java 10 开始,默认情况下启用容器集成。但是,这对您来说可能不是一个明显的改进,因为在 Java 8 更新 131 中引入了相同的更改,尽管它需要启用实验选项并使用-XX:+UseCGroupMemoryLimitForHeap。

9. CDS档案

为了使 JVM 启动得更快,CDS Archives 自 Java 8 发布以来经历了一些变化。从 JDK 12 开始,默认情况下启用在构建过程中创建 CDS 档案 ( JEP 341 )。JDK 13 ( JEP 350 ) 中的一项增强功能允许在每次应用程序运行后更新档案。

这篇文章演示了如何使用此功能来缩短应用程序的启动时间。

10. Java Flight Recorder 和 Java Mission Control

Java Flight Recorder ( JEP 328 ) 允许以较低的(目标 1%)性能成本监视和分析正在运行的 Java 应用程序。Java Mission Control允许摄取和可视化 JFR 数据。参阅教程以大致了解如何使用它以及从中可以获得什么。

11. 你应该从 Java 8 迁移到 Java 17 吗?

简而言之,是的,你应该这样做。如果您有一个大型、高负载的企业应用程序并且仍然使用 Java 8,那么您肯定会看到更好的性能、更快的启动时间、迁移后更低的内存占用。开发该应用程序的程序员也应该更开心,因为语言本身有许多改进。

然而,这样做的成本很难估计,并且会因使用的应用程序服务器、库和应用程序本身的复杂性(或者更确切地说,它使用/重新实现的低级功能的数量)而有很大差异。

如果您的应用程序没有自定义类加载器,没有严重依赖 Unsafe、大量 sun.misc 或 sun.security 用法,那么您可能会没事。请参阅这篇文章,了解您可能需要进行的一些更改。

从版本 8 开始,Java 中删除了一些东西,包括 Nashorn JS 引擎、Pack200 API 和工具、Solaris/Sparc 端口、AOT 和 JIT 编译器、Java EE 和 Corba 模块。有些东西仍然存在,但不赞成删除,例如 Applet API 或安全管理器。由于有充分的理由将它们移除,因此无论如何您都应该重新考虑它们在您的应用程序中的使用。

小结

Java17主要有如下几个特性
JEP 306: Restore Always-Strict Floating-Point Semantics
JEP 356: Enhanced Pseudo-Random Number Generators
JEP 382: New macOS Rendering Pipeline
JEP 391: macOS/AArch64 Port
JEP 398: Deprecate the Applet API for Removal
JEP 403: Strongly Encapsulate JDK Internals
JEP 406: Pattern Matching for switch (Preview)
JEP 407: Remove RMI Activation
JEP 409: Sealed Classes
JEP 410: Remove the Experimental AOT and JIT Compiler
JEP 411: Deprecate the Security Manager for Removal
JEP 412: Foreign Function & Memory API (Incubator)
JEP 414: Vector API (Second Incubator)
JEP 415: Context-Specific Deserialization Filters

Java 17 新特性相关推荐

  1. 2022年最细Java 17新特性,是真的猛,被征服了!

    SpringBoot 正式支持Java 17,Kafka3.0弃用Java8 Spring Boot 2.5.5是Spring Boot 第一个支持Java 17的版本.现在你已经可以从Spring ...

  2. Java 17新特性,快到起飞?惊呆了!

    都说Java 8 是YYDS,那你注意到 Java 17 也是长期支持版本吗?目前按计划 JDK 19 将于今年 9 月发布 SpringBoot 正式支持Java 17,Kafka3.0弃用Java ...

  3. Java 17新特性,快到起飞?

    都说Java 8 是YYDS,那你注意到 Java 17 也是长期支持版本吗?目前按计划 JDK 19 将于今年 9 月发布 SpringBoot 正式支持Java 17,Kafka3.0弃用Java ...

  4. Java 17 新特性:密封类

    Java 17推出的新特性Sealed Classes经历了2个Preview版本(JDK 15中的JEP 360.JDK 16中的JEP 397),最终定稿于JDK 17中的JEP 409.Seal ...

  5. Java 17 新特性尝鲜

    JDK 17更新了包括14个特性,具体如下表所示: Restore Always-StrictFloating-Point Semantics 恢复始终严格模式(Always-Strict)的浮点语义 ...

  6. Java 17 VS Java 8: 新旧对决,这些Java 17新特性你不容错过

  7. Java 8新特性——default方法(defender方法)介绍

    转载自 Java 8新特性--default方法(defender方法)介绍 我们都知道在Java语言的接口中只能定义方法名,而不能包含方法的具体实现代码.接口中定义的方法必须在接口的非抽象子类中实现 ...

  8. Java 9 新特性概述

    转载自 Java 9 新特性概述 Java 9 正式发布于 2017 年 9 月 21 日 .作为 Java8 之后 3 年半才发布的新版本,Java 9 带 来了很多重大的变化.其中最重要的改动是 ...

  9. Java 11新特性

    转载来源:https://juejin.im/post/5bb08accf265da0a87266d2a Java 11新特性 概述 美国当地时间9月25日,Oracle 官方宣布 Java 11 ( ...

最新文章

  1. 人脸识别中的margin损失函数
  2. 存储过程编写经验和优化措施
  3. JavaScript 要点(十四)HTML DOM 元素(节点)
  4. 1033 旧键盘打字 (20 分)(c语言)
  5. 【Java】线程通信的例子:用两个线程打印 1-100;生产者消费者问题
  6. 云服务器系统盘升级会不会丢失数据,云服务器 系统盘快还是数据盘快
  7. 20135302魏静静——linux课程第六周实验及总结
  8. mysql 锁怎么使用_Mysql锁一般使用
  9. Android嵌套滑动冲突
  10. 遇到local variable ‘e‘ referenced before assignment这样的问题应该如何解决
  11. vue封装element-ui的table组件,灵活配置表头实现表格内编辑,按钮,链接等功能。...
  12. 数据密集型系统设计pdf下载
  13. 计算机毕业论文技术可行性怎么写,毕业论文怎么写可行性分析?
  14. winhex使用教程(详细版)
  15. 存储、计算、分布式知识点思维导图(收集整理适合小白)
  16. asp.net html silverlight 传参数,Silverlight和ASP.NET相互传参的两种常用方式(QueryString,Cookie)...
  17. 极客假日礼物指南(我们喜欢的极客资料)
  18. springboot+jsp人事工资管理系统 java ssm maven
  19. radis安装和使用
  20. 大数据下的小媒体——访新蓝网副总监洪永和

热门文章

  1. 关于Clipper库使用小结
  2. 图像采集及传输速率计算
  3. MPEG4 笔记(FTYP,MOOV,MVHD)
  4. MsgQ机制,实现H5游戏的模块彻底分离
  5. 基于PageRank的复杂网络社区发现
  6. c语言实现翻页,css3实现翻页卡片
  7. java图片不失真压缩_(转)图片等比压缩,确保不失真
  8. 图片放大无失真算法 opengles实现
  9. 路由器无线桥接的方法
  10. 【无标题】 6UVPX 总线架构的高性能实时信号处理