跟上 Java 频繁发布的功能并不容易。如果您错过了密封类、文本块、记录、新的字符串方法或 Optional 类,让我们修复它。
这对于保持 Java 的新鲜度和相关性非常好,但它很容易在引入功能时错过它们。本文汇总了几个有用的新功能并对其进行了概述。
可选类
空指针异常是所有错误中最经典的错误之一。虽然它可能很熟悉,但要提防这是一个非常冗长的问题。至少在 Java 8 引入(以及 Java 10 改进)Optional该类之前是这样。
本质上,Optional该类允许您包装一个变量,然后使用包装器的方法更简洁地处理空值。清单 1 有一个花园类型空指针错误的示例,其中类引用 ,foo为空,并且foo.getName()在其上访问了方法 , 。
清单 1. 没有 Optional 的空指针
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 检查的方法。然而,这最终变得相当冗长。但Optional也有功能处理的方法。例如,清单 2 展示了如何使用ifPresent()(注意与 的一个字母不同isPresent())仅在存在值的情况下运行输出代码。
清单 2. 仅当值存在时才运行代码
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()来提供函数引用,以获得在值非空时不运行调用的性能优势。
Record 类(预览功能)
构建 Java 应用程序的一个常见需求是所谓的不可变 DTO(数据传输对象)。DTO 用于对来自数据库、文件系统和其他数据存储的数据进行建模。传统上,DTO 是通过创建一个类来创建的,该类的成员是通过构造函数设置的,没有 getter 来访问它们。Java 14 引入并改进了 Java 15,record为此目的提供了简写的新关键字。
record清单 3 说明了在引入类型之前的典型 DTO 定义和用法。
清单 3. 一个简单的不可变 DTO
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我们可以使用清单 4 中所示的关键字消除大部分样板文件。
清单 4. 使用记录关键字
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()
请注意,不能对记录进行子分类。
新的字符串方法
在 Java 10 和 Java 12 中,String添加了几个有用的新方法。除了字符串操作方法之外,还引入了两种简化文本文件访问的新方法。
StringJava 10 中的新方法:
isBlank():如果字符串为空或字符串仅包含空格(这包括制表符),则返回 true。NoteisBlank()与 不同isEmpty(),后者仅在长度为 0 时返回 true。
lines():将字符串拆分为字符串流,每个字符串包含一行。线条由/r或/n或定义/r/n。例如,考虑下面的清单 5。
strip(), stripLeading(), stripTrailing(): 分别从开头和结尾、仅开头和仅结尾删除空格。
repeat(int times):返回一个字符串,该字符串采用原始字符串并重复指定的次数。
readString():允许从文件路径直接读取到字符串,如清单 6 所示。
writeString(Path path): 将字符串直接写入指定路径的文件中。
StringJava 12 中的新方法:
indent(int level):将字符串缩进指定的数量。负值只会影响前导空格。
transform(Function f):将给定的 lambda 应用于字符串。
清单 5. String.lines() 示例
Path path = Path.of("myFile.txt");
String text = Files.readString(path);
System.out.println(text);
切换表达式
Java 12 引入了switch允许switch在语句中内联使用的表达式。换句话说,switch表达式返回一个值。Java 12 还提供了一种箭头语法,无需显式break地防止失败。Java 13 更进一步,引入了yield关键字来明确表示switchcase 返回的值。Java 14 采用了新的switch表达式语法作为一个完整的特性。
让我们看一些例子。首先,清单 7 有一个(非常人为的)switch传统(Java 8)格式的语句示例。此代码使用变量 ( message) 来输出已知数字的名称。
清单 7. 老式 Java 开关
class Main {
public static void main(String args[]) {
int size = 3;
String message = "";
switch (size){
case 1 :
message = "one";
case 3 :
message = "three";
break;
default :
message = "unknown";
break;
}
System.out.println("The number is " + message);
}
}
现在这段代码非常冗长和挑剔。其实里面已经有错误了!仔细寻找丢失的break. 清单 8 通过使用switch表达式对其进行了简化。
清单 8. 新的 switch 表达式
class NewSwitch {
public static void main(String args[]) {
int size = 3;
System.out.println("The number is " +
switch (size) {
case 1 -> "one";
case 3 -> "three";
default -> "unknown";
}
);
}
}
在清单 8 中,您可以看到switch表达式直接在System.out.println调用内部。这已经是一个巨大的可读性胜利,并且消除了多余的消息变量。此外,箭头语法通过消除语句来减少代码占用break。(yield不使用箭头语法时使用关键字。)
文本块
Java 13 通过引入文本块解决了长期以来在 Java 中处理复杂文本字符串的烦恼。Java 14 改进了这种支持。
JSON、XML 和 SQL 之类的东西可能会让您因多个嵌套的转义层而发疯。正如规范所解释的:
在 Java 中,在字符串文字中嵌入 HTML、XML、SQL 或 JSON 的片段……通常需要在包含该片段的代码编译之前使用转义和连接进行大量编辑。该片段通常难以阅读且难以维护。
看看清单 9,其中新的文本块语法用于创建 JSON 片段。
清单 9. 使用文本块的 JSON
class TextBlock {
public static void main(String args[]) {
String json = """
{
"animal" : "Quokka",
"link" : "https://en.wikipedia.org/wiki/Quokka"
}
""";
System.out.println(json);
}
}
在清单 9 中,看不到转义字符。注意三重双引号语法。
密封类
Java 15(JEP260) 引入了密封类的概念。简而言之,newsealed关键字允许您定义哪些类可以子类化接口。在这种情况下,一个例子值一千字。请参见清单 10。
清单 10. 密封类示例
public abstract sealed class Pet
permits Cat, Dog, Quokka {...}
这里界面设计者使用sealed关键字来指定允许哪些类扩展Pet该类。
总的来说,很明显,Java 发布的新方法正在发挥作用。我们看到许多新想法通过 JEP(JDK 增强提案)流程转化为实际可用的 Java 功能。这对 Java 开发人员来说是个好消息。这意味着我们正在一个活生生的、不断发展的语言和平台中工作。
需要学习更多Java资料 关注博主,私聊博主免费获取