What’s New in Java 15 – Java 15中的新内容

最后修改: 2020年 11月 22日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.绪论

Java 15 reached general availability in September 2020 and is the next short-term release for the JDK platform. It builds on several features from earlier releases and also provides some new enhancements.

Java 15在2020年9月达到普遍可用,是JDK平台的下一个短期版本。它建立在早期版本的几个功能基础上,还提供了一些新的增强功能。

In this post, we’ll look at some of the new features of Java 15, as well as other changes that are of interest to Java developers.

在这篇文章中,我们将看看Java 15的一些新功能,以及Java开发者感兴趣的其他变化。

2. Records (JEP 384)

2.记录(JEP 384)

The record is a new type of class in Java that makes it easy to create immutable data objects.

record是Java中的一种新类型的类,它使创建不可变的数据对象变得容易。

Originally introduced in Java 14 as an early preview, Java 15 aims to refine a few aspects before becoming an official product feature.

最初在 Java 14 中作为早期预览版推出,Java 15 旨在在成为正式产品功能之前完善几个方面

Let’s look at an example using current Java and how it could change with records.

让我们看一个使用当前Java的例子,以及它如何通过记录来改变.

2.1. Without Records

2.1.没有记录

Prior to records, we would create an immutable data transfer object (DTO) as:

在记录之前,我们会创建一个不可变的数据传输对象(DTO)作为。

public class Person {
    private final String name;
    private final int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

Notice that there’s a lot of code here to create an immutable object that really just holds the state. All of our fields are explicitly defined using final, we have a single all-arguments constructor, and we have an accessor method for every field. In some cases, we might even declare the class itself as final to prevent any sub-classing.

请注意,这里有大量的代码来创建一个不可变的对象,而这个对象实际上只是持有状态。我们所有的字段都是用final明确定义的,我们有一个单一的全参数构造函数,并且我们为每个字段都有一个访问方法。在某些情况下,我们甚至可以将类本身声明为final,以防止任何子类。

In many cases, we would also go a step further and override the toString method to provide meaningful logging output. We would probably also want to override the equals and hashCode methods to avoid unexpected consequences when comparing two instances of these objects.

在许多情况下,我们还会更进一步,覆盖toString方法以提供有意义的日志输出。我们可能还想覆盖equalshashCode方法,以避免在比较这些对象的两个实例时出现意外的后果。

2.2. With Records

2.2.有记录

Using the new record class, we can define the same immutable data object in a much more compact way:

使用新的record类,我们可以以更紧凑的方式定义相同的不可变数据对象。

public record Person(String name, int age) {
}

A few things have happened here. First and foremost, the class definition has a new syntax that is specific for records. This header is where we provide the details about the fields inside the record.

这里发生了几件事。首先,最重要的是,类定义有一个新的语法,是专门针对记录s的。这个头是我们提供关于记录内部字段的细节的地方。

Using this header, the compiler can infer the internal fields. This means we don’t need to define specific member variables and accessors, as they’re provided by default. We also don’t have to provide a constructor.

使用这个头文件,编译器可以推断出内部字段。这意味着我们不需要定义特定的成员变量和访问器,因为它们是默认提供的。我们也不需要提供一个构造函数。

Additionally, the compiler provides sensible implementations for the toString, equals, and hashCode methods.

此外,编译器为toStringequalshashCode方法提供合理的实现。

While records eliminate a lot of boilerplate code, they do allow us to override some of the default behaviors. For example, we could define a canonical constructor that does some validation:

虽然记录s消除了大量的模板代码,它们确实允许我们覆盖一些默认行为。例如,我们可以定义一个典型的构造函数,进行一些验证。

public record Person(String name, int age) {
    public Person {
        if(age < 0) {
            throw new IllegalArgumentException("Age cannot be negative");
        }
    }
}

It’s worth mentioning that records do have some restrictions. Among other things, they are always final, they cannot be declared abstract, and they can’t use native methods.

值得一提的是,记录s确实有一些限制。其中,它们总是final,它们不能被声明为abstract,而且它们不能使用native方法

3. Sealed Classes (JEP 360)

3.封闭式班级(JEP 360)

Currently, Java provides no fine-grained control over the inheritance. Access modifiers such as public, protected, private, as well as the default package-private, provide very coarse-grained control.

目前,Java没有提供对继承的细粒度控制。诸如publicprotectedprivate以及默认的package-private这样的访问修饰符提供了非常粗略的控制。

To that end, the goal of sealed classes is to allow individual classes to declare which types may be used as sub-types. This also applies to interfaces and determining which types can implement them.

为此,密封的目标是允许各个类声明哪些类型可以作为子类型使用。这也适用于接口和确定哪些类型可以实现它们。

Sealed classes involve two new keywords — sealed and permits:

封闭类涉及两个新的关键字–密封许可

public abstract sealed class Person
    permits Employee, Manager {
 
    //...
}

In this example, we’ve declared an abstract class named Person. We’ve also specified that the only classes that can extend it are Employee and Manager. Extending the sealed class is done just as it is today in Java, using the extends keyword:

在这个例子中,我们声明了一个名为Person的抽象类。我们还指定了能够扩展它的唯一类是EmployeeManager。扩展sealed类的方法就像今天在Java中一样,使用extends关键字。

public final class Employee extends Person {
}

public non-sealed class Manager extends Person {
}

It’s important to note that any class that extends a sealed class must itself be declared sealed, non-sealed, or final. This ensures the class hierarchy remains finite and known by the compiler.

值得注意的是,任何扩展密封类的类本身必须被声明为密封非密封最终。这可以确保类的层次结构保持有限,并为编译器所了解。

This finite and exhaustive hierarchy is one of the great benefits of using sealed classes. Let’s see an example of this in action:

这种有限的、详尽的层次结构是使用密封的类的巨大好处之一。让我们看看这个例子的实际应用。

if (person instanceof Employee) {
    return ((Employee) person).getEmployeeId();
} 
else if (person instanceof Manager) {
    return ((Manager) person).getSupervisorId();
}

Without a sealed class, the compiler can’t reasonably determine that all possible sub-classes are covered with our if-else statements. Without an else clause at the end, the compiler would likely issue a warning indicating our logic doesn’t cover every case.

如果没有一个密封的类,编译器无法合理地确定所有可能的子类都被我们的 if-else语句所覆盖。如果最后没有else子句,编译器可能会发出警告,表明我们的逻辑没有涵盖所有的情况。

4. Hidden Classes (JEP 371)

4.隐性类(JEP 371)

A new feature being introduced in Java 15 is known as hidden classes. While most developers won’t find a direct benefit from them, anyone who works with dynamic bytecode or JVM languages will likely find them useful.

Java 15 中引入的一项新功能被称为隐藏的类。虽然大多数开发人员不会发现它们的直接好处,但任何使用动态字节码或JVM语言的人都可能会发现它们很有用。

The goal of hidden classes is to allow the runtime creation of classes that are not discoverable. This means they cannot be linked by other classes, nor can they be discovered via reflection. Classes such as these typically have a short lifecycle, and thus, hidden classes are designed to be efficient with both loading and unloading.

隐藏类的目标是允许在运行时创建不能被发现的类。这意味着它们不能被其他类链接,也不能通过reflection发现它们。诸如此类的类通常具有较短的生命周期,因此,隐藏类被设计为在加载和卸载方面都很高效。

Note that current versions of Java do allow for the creation of anonymous classes similar to hidden classes. However, they rely on the Unsafe API. Hidden classes have no such dependency.

请注意,当前版本的Java确实允许创建类似于隐藏类的匿名类。然而,它们依赖于Unsafe API。隐藏类则没有这种依赖性。

5. Pattern Matching Type Checks (JEP 375)

5.模式匹配类型检查(JEP 375)

The pattern matching feature was previewed in Java 14, and Java 15 aims to continue its preview status with no new enhancements.

模式匹配功能在Java 14中进行了预览,而Java 15旨在继续保持其预览状态,没有新的增强功能。

As a review, the goal of this feature is to remove a lot of boilerplate code that typically comes with the instanceof operator:

作为回顾,这个功能的目标是删除大量通常与instanceof操作符一起出现的模板代码。

if (person instanceof Employee) {
    Employee employee = (Employee) person;
    Date hireDate = employee.getHireDate();
    //...
}

This is a very common pattern in Java. Whenever we check if a variable is a certain type, we almost always follow it with a cast to that type.

这是Java中一个非常常见的模式。每当我们检查一个变量是否是某种类型时,我们几乎总是在它后面加上一个投射到该类型。

The pattern matching feature simplifies this by introducing a new binding variable:

模式匹配功能通过引入一个新的绑定变量简化了这一点。

if (person instanceof Employee employee) {
    Date hireDate = employee.getHireDate();
    //...
}

Notice how we provide a new variable name, employee, as part of the type check. If the type check is true, then the JVM automatically casts the variable for us and assigns the result to the new binding variable.

注意我们是如何提供一个新的变量名employee,作为类型检查的一部分。如果类型检查是true,那么JVM会自动为我们转换变量并将结果分配给新的绑定变量

We can also combine the new binding variable with conditional statements:

我们还可以将新的绑定变量与条件语句相结合。

if (person instanceof Employee employee && employee.getYearsOfService() > 5) {
    //...
}

In future Java versions, the goal is to expand pattern matching to other language features such as switch statements.

在未来的Java版本中,目标是将模式匹配扩展到其他语言功能,如switch语句。

6. Foreign Memory API (JEP 383)

6.外国内存API(JEP 383)

Foreign memory access is already an incubating feature of Java 14. In Java 15, the goal is to continue its incubation status while adding several new features:

外国内存访问已经是Java 14的一个孵化功能。在Java 15中,目标是继续保持其孵化状态,同时增加几个新功能。

  • A new VarHandle API, to customize memory access var handles
  • Support for parallel processing of a memory segment using the Spliterator interface
  • Enhanced support for mapped memory segments
  • Ability to manipulate and dereference addresses coming from things like native calls

Foreign memory generally refers to memory that lives outside the managed JVM heap. Because of this, it’s not subject to garbage collection and can typically handle incredibly large memory segments.

外来内存通常指的是生活在管理的JVM堆之外的内存。正因为如此,它不受垃圾收集的影响,通常可以处理大得惊人的内存段。

While these new APIs likely won’t impact most developers directly, they will provide a lot of value to third-party libraries that deal with foreign memory. This includes distributed caches, denormalized document stores, large arbitrary byte buffers, memory-mapped files, and more.

虽然这些新的API可能不会直接影响大多数开发者,但它们将为处理外来内存的第三方库提供很多价值。这包括分布式缓存、反规范化文档存储、大型任意字节缓冲区、内存映射文件等等。

7. Garbage Collectors

7.垃圾收集器

In Java 15, both ZGC (JEP 377) and Shenandoah (JEP 379) will be no longer be experimental. Both will be supported configurations that teams can opt to use, while the G1 collector will remain the default.

在 Java 15 中,ZGC(JEP 377)和 Shenandoah(JEP 379)都将不再是实验性的。两者都将成为支持的配置,团队可以选择使用,而G1收集器仍将是默认配置。

Both were previously available using experimental feature flags. This approach allows developers to test the new garbage collectors and submit feedback without downloading a separate JDK or add-on.

两者之前都是使用实验性功能标志的。这种方法允许开发者测试新的垃圾收集器并提交反馈,而无需下载单独的JDK或插件。

One note on Shenandoah: it isn’t available from all vendor JDKs — most notably, Oracle JDK doesn’t include it.

关于Shenandoah的一个注意事项:并非所有供应商的JDK都提供该功能–最明显的是,Oracle JDK不包括该功能。

8. Other Changes

8.其他变化

There are several other noteworthy changes in Java 15.

在Java 15中还有几个值得注意的变化。

After multiple rounds of previews in Java 13 and 14, text blocks will be a fully supported product feature in Java 15.

经过 Java 13 和 14 的多轮预览,文本块将成为 Java 15 中完全支持的产品功能。

Helpful null pointer exceptions, originally delivered in Java 14 under JEP 358, are now enabled by default.

有用的空指针异常,最初在Java 14的JEP 358中提供,现在默认启用。

The legacy DatagramSocket API has been rewritten. This is a follow-on to a rewrite in Java 14 of the Socket API. While it won’t impact most developers, it is interesting as it’s a prerequisite for Project Loom.

传统的DatagramSocket API已被重写。这是对Java 14中Socket API的重写的后续。虽然它不会影响大多数开发人员,但它是Project Loom的先决条件,因此非常有趣。

Also of note, Java 15 includes cryptographic support for Edwards-Curve Digital Signature Algorithm. EdDSA is a modern elliptic curve signature scheme that has several advantages over the existing signature schemes in the JDK.

另外值得注意的是,Java 15包括对Edwards-curve数字签名算法的加密支持。EdDSA是一种现代椭圆曲线签名方案,与JDK中现有的签名方案相比,它有几个优点。

Finally, several things have been deprecated in Java 15. Biased locking, Solaris/SPARC ports, and RMI Activation are all removed or scheduled for removal in a future release.

最后,有几件事在Java 15中已经被废弃了。有偏见的锁定、Solaris/SPARC端口和RMI激活都被删除或计划在未来的版本中删除。

Of note, The Nashorn JavaScript engine, originally introduced in Java 8, is now removed. With the introduction of GraalVM and other VM technologies recently, it’s clear Nashorn no longer has a place in the JDK ecosystem.

值得注意的是,最初在Java 8中引入的Nashorn JavaScript引擎现已被移除。随着最近GraalVM和其他虚拟机技术的引入,很明显Nashorn在JDK的生态系统中不再有地位。

9. Conclusion

9.结语

Java 15 builds on several features of past releases, including records, text blocks, new garbage collection algorithms, and more. It also adds new preview features, including sealed classes and hidden classes.

Java 15建立在过去版本的若干特性之上,包括记录、文本块、新的垃圾收集算法等。它还增加了新的预览功能,包括密封类和隐藏类

As Java 15 is not a long-term-support release, we can expect support for it to end in March 2021. At that time, we can look forward to Java 16, followed soon after with a new long-term-support version in Java 17.

由于Java 15不是一个长期支持的版本,我们可以预期对它的支持将在2021年3月结束。届时,我们可以期待Java 16,然后很快就会有一个新的长期支持的Java 17版本。