在评审结束后,JEP 447(super() 前置语句 (预览)) 已在 JDK 22 中交付。该 JEP 来自 Project Amber 项目,提议允许在构造函数的 super()
调用之前出现不引用正在创建的实例的语句,并保留构造函数现有的安全性和初始化保证。Oracle 技术顾问成员 Gavin Bierman 为 Java 社区提供了这个 JEP 的初始规范,供社区评审并提供反馈意见。
传统上,要求 Java 构造函数将对另一个构造函数的显式调用作为第一条语句。这个约束确保了自上而下的执行顺序,并防止对未初始化字段的访问,极大地限制了构造函数逻辑的表达性和可读性。考虑下面的例子:
public class PositiveBigInteger extends BigInteger {
public PositiveBigInteger(long value) {
super(value); // Potentially unnecessary work
if (value <= 0)
throw new IllegalArgumentException("non-positive value");
}
}
复制代码
通过在调用超类构造函数之前验证其参数来声明快速失败的构造函数会更好。JEP 447 放宽了这些限制,允许在显式构造函数调用之前出现不引用正在创建的实例的语句。有了这个功能,上面的代码可以简化为:
public class PositiveBigInteger extends BigInteger {
public PositiveBigInteger(long value) {
if (value <= 0)
throw new IllegalArgumentException("non-positive value");
super(value);
}
}
复制代码
考虑另一种情况,比如子类构造函数需要为超类构造函数准备参数。以前,由于超类构造函数调用必须作为第一条语句,这就需要使用辅助方法。
public class SubClass extends SuperClass {
public SubClass(Certificate certificate) {
super(prepareByteArray(certificate));
}
private static byte[] prepareByteArray(Certificate certificate) {
// Logic to prepare byte array from certificate
// ...
return byteArray;
}
}
复制代码
在这个例子中,prepareByteArray
方法在将 Certificate
对象传递给 SuperClass
构造函数之前对它进行处理。有了 JEP 447,这个过程变得更加简洁和直观。
public class SubClass extends SuperClass {
public SubClass(Certificate certificate) {
// Directly include the logic to prepare byte array
PublicKey publicKey = certificate.getPublicKey();
if (publicKey == null) {
throw new IllegalArgumentException("Null certificate");
}
byte[] byteArray = switch (publicKey) {
case RSAPublicKey rsaKey -> rsaKey.getEncoded();
case DSAPublicKey dsaKey -> dsaKey.getEncoded();
default -> throw new UnsupportedOperationException("Unsupported key type");
};
super(byteArray);
}
}
复制代码
在这个新的例子中,SubClass
的构造函数直接包含处理 Certificate
对象的逻辑。这种直接的方法增强了可读性,减少对使用辅助方法的需求,展示了 JEP 447 在实际应用场景中的好处。
JEP 447 不仅提供了更大的灵活性,还保留了构造函数行为的基本保证,确保子类构造函数不会干扰超类的实例化。这个更新不需要对 Java 虚拟机(JVM)做任何修改,仅依赖 JVM 现有的能力来验证和执行构造函数调用之前的代码。
随着 Java 的不断发展,JEP 447 清楚地表明了 Java 在不断适应现代编程实践。它反映了在引入新特性和保持 Java 生态系统健壮性之间的平衡。对于 Java 开发者来说,这意味着有机会探索更高效的编码实践,同时仍然保持对编程语言的核心原则。
原文链接:
https://www.infoq.com/news/2024/01/java-constructors-enhancement/
评论