Java 17 新特性

如果您想比较不同版本的 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基础,java)