近年,随着新的发布节奏的采用,Java悄然经历了其发展中最大的变化之一。这个大胆的新计划使Java开发人员每六个月就能得到一个新的功能版本。
这对于保持Java的新鲜感和相关性来说是非常好的,但这也使得它很容易错过功能的引入。这篇文章总结了几个有用的新特性,并对它们进行了概述。
The Optional Class
空指针异常是所有错误中最经典的一种。虽然它可能很熟悉,但它是一个需要防范的非常冗长的问题。至少在Java 8引入(和Java 10完善)Optional类之前是这样。
从本质上讲,Optional类允许你包装一个变量,然后使用包装器的方法来更简洁地处理空值问题。
下面有一个空指针错误的例子,其中一个类的引用foo是空的,一个方法foo.getName()被访问。
public class MyClass {
public static void main(String args[]) {
InnerClass foo = null;
System.out.println("foo = " + foo.getName());
}
}
class InnerClass {
String name = "";
public String getName(){
return this.name;
}
}
复制代码
根据你的需要,Optional提供了一些处理这种情况的方法。它有一个isPresent()方法,你可以用它来做一个if-check。然而,这最终是相当冗长的。但是Optional也有功能处理的方法。
例如,下面的代码显示了你如何使用ifPresent()--注意与isPresent()有一个字母的区别--只在有值存在的情况下运行输出代码。
import java.util.Optional;
public class MyClass {
public static void main(String args[]) {
InnerClass foo = null; //new InnerClass("Test");
Optional fooWrapper = Optional.ofNullable(foo);
fooWrapper.ifPresent(x -> System.out.println("foo = " + x.getName()));
//System.out.println("foo = " + fooWrapper.orElseThrow());
}
}
class InnerClass {
String name = "";
public InnerClass(String name){
this.name = name;
}
public String getName(){
return this.name;
}
}
复制代码
提示:当使用Optional时,如果你使用orElse()方法通过方法调用提供一个默认值,考虑使用orElseGet()来代替提供一个函数引用,以获得性能上的好处,如果值是非空的,就不会运行调用。
The Record Class
构建Java应用的一个常见需求是所谓的不可变的DTO(数据传输对象)。DTOs用于对来自数据库、文件系统和其他数据存储的数据进行建模。传统上,DTOs是通过制作一个类来创建的,其成员通过构造函数来设置,没有访问它们的getters。Java 14引入了新的记录关键字,Java 15在此基础上进行了改进,为这一目的提供了一种速记方式。
下面的例子说明了一个典型的DTO定义和record类型引入前的用法。
public class MyClass {
public static void main(String args[]) {
Pet myPet = new Pet("Sheba", 10);
System.out.println(String.format("My pet %s is aged %s", myPet.getName(), myPet.getAge()));
}
}
class Pet {
String name;
Integer age;
public Pet(String name, Integer age){
this.name = name;
this.age = age;
}
public String getName(){
return this.name;
}
public Integer getAge(){
return this.age;
}
}
复制代码
如下面的例子所示,我们可以使用record关键字来消除大部分的模板。
public class MyClass {
public static void main(String args[]) {
Pet myPet = new Pet("Sheba", 10);
System.out.println(String.format("My pet %s is aged %s", myPet.getName(), myPet.getAge()));
}
}
public record Pet(String name, Integer age) {}
复制代码
请注意,使用数据对象的客户端代码并没有改变;它的行为就像传统定义的对象一样。record关键字足够聪明,可以通过简单的定义足迹推断出存在哪些字段。
record类型还定义了equals()、hashCode()和toString()的默认实现,同时也允许开发者重写这些。 你也可以提供一个自定义的构造函数。
请注意,record不能被子类化。
感谢观看,这是6个Java不容错过的新特性第1篇文章,如果您有兴趣,可以关注一下我,方便查看后续文章,一起学习,共同进步,不胜感激!