很重要的提醒
Java 15即将于2020年9月15发布.
- Java 14: instanceof的模式匹配(预览)
- Java 14:Switch表达式
- Java 14:文本块(第二预览)
- Java14: Record(预览)
- Java 13: Switch表达式
- Java 13预览: 文本块
仅摘录部分更新特性.全部特性可以在 https://openjdk.java.net/projects/jdk/15/找到.
全部更新:
- 爱德华兹曲线数字签名算法(EdDSA)
- 密封课程(预览)
- 隐藏的课程
- 删除Nashorn JavaScript引擎
- 重新实现旧版DatagramSocket API
- 禁用和弃用偏置锁定
- instanceof的模式匹配(第二预览)
- ZGC:可扩展的低延迟垃圾收集器
- 文字块
- Shenandoah:低暂停时间的垃圾收集器
- 删除Solaris和SPARC端口
- 外部存储器访问API(第二个孵化器)
- 记录(第二预览)
- 弃用RMI激活以进行删除
密封类或接口(预览)
密封类或接口可以用来限制只有特定的类或接口才能继承或实现它们.
用sealed修饰符来声明密封类.然后使用permits来指定允许扩展密封类的类.
示例:
1
2 public abstract sealed class Shape
permits Circle, Rectangle, Square {}
同时,子类在不同的包中也是可以的:
1
2
3
4 public abstract sealed class Shape
permits com.example.polar.Circle,
com.example.quad.Rectangle,
com.example.quad.simple.Square {...}
如果都在同一个包中,则可以像下面这样声明:
1
2
3
4
5 abstract sealed class Shape { }
class Circle extends Shape { }
class Rectangle extends Shape { }
class Square extends Shape { }
密封类针对子类(由permits修饰符指定的类)有三个约束:
1. 密封类及其允许的子类必须属于同一模块,并且如果在未命名的模块中声明,则必须属于同一包。
2. 每个允许的子类都必须直接扩展密封的类。
3. 每个允许的子类都必须选择一个修饰符来描述其如何继续其父类发起的密封:
3.1 可以声明一个允许的子类,final以防止其在类层次结构中的进一步扩展。
3.2 可以声明一个允许的子类,sealed以允许其层次结构的一部分扩展到超出其密封超类所设想的范围,但以受限的方式。
3.3 可以声明一个允许的子类,non-sealed以便其层次结构的一部分恢复为未知子类可以扩展的扩展。(密封类不能阻止其允许的子类这样做。)
密封接口和类的使用方式类似:
1
2
3
4
5
6
7 public sealed interface Expr
permits ConstantExpr, PlusExpr, TimesExpr, NegExpr {}
public final class ConstantExpr implements Expr {}
public final class PlusExpr implements Expr {}
public final class TimesExpr implements Expr {}
public final class NegExpr implements Expr {}
密封类与record可以配合使用:
1
2
3
4
5
6
7 public sealed interface Expr
permits ConstantExpr, PlusExpr, TimesExpr, NegExpr {}
public record ConstantExpr(int i) implements Expr {}
public record PlusExpr(Expr a, Expr b) implements Expr {}
public record TimesExpr(Expr a, Expr b) implements Expr {}
public record NegExpr(Expr e) implements Expr {}
instanceof模式匹配(第二预览)
instanceof模式匹配在Java 14中新增,在Java 15中开启第二预览.功能方面没有任何更改.
文本块(Text Blocks)
文本块在Java 13中开启预览,Java 14开启第二预览.在Java 15中发布.在Java 15中文本块没有任何更改.
record(第二预览)
1. 内部声明record
Java 15中增加了在方法内部使用record:
本地记录是嵌套记录的一种特殊情况。像所有嵌套记录一样,本地记录也是隐式静态的。这意味着它们自己的方法无法访问封闭方法的任何变量;反过来,这避免了捕获立即封闭的实例,该实例将以静默方式将状态添加到记录中。本地记录是隐式静态的,这与不是隐式静态的本地类相反。实际上,局部类永远不会是静态的(隐式或显式),并且始终可以访问封闭方法中的变量。
1
2
3
4
5
6
7
8
9
10 List findTopMerchants(List merchants, int month) {
// Local record
record MerchantSales(Merchant merchant, double sales) {}
return merchants.stream()
.map(merchant -> new MerchantSales(merchant, computeSales(merchant, month)))
.sorted((m1, m2) -> Double.compare(m2.sales(), m1.sales()))
.map(MerchantSales::merchant)
.collect(toList());
}
2. record的注解
如下的注解示例:
1
2
3
4
5
6
7 public final class Card {
private final @MyAnno Rank rank;
private final @MyAnno Suit suit;
@MyAnno Rank rank() { return this.rank; }
@MyAnno Suit suit() { return this.suit; }
}
可以优化为:
1 public record Card(@MyAnno Rank rank, @MyAnno Suit suit) { }
返回到record上的注解,这些注解出现在适用的相应程序点处。换句话说,传播是在程序员使用@Target 元注解的控制下进行的。传播规则是系统且直观的,并且遵循所有适用的规则:
1. 如果记录组件上的注解适用于字段声明,则注解将出现在相应的private字段上。
2. 如果记录组件上的注解适用于方法声明,则该注解将出现在相应的访问器方法上。
3. 如果记录组件上的注解适用于形式参数,则如果未显式声明注解,则该注解将出现在规范构造函数的相应形式参数上;如果显式声明,则注解将出现在紧凑构造函数的相应形式参数上。
4. 如果记录组件上的注解适用于某个类型,则传播规则与声明注解的传播规则相同,不同之处在于,该注解出现在相应的类型用途上而不是声明上。