Java8-15新功能概述

本文概述了Java 8至15的主要新功能,包括函数式编程与Lambda表达式、Stream API、Optional、JShell(Java 9)、不可变集合的工厂方法(Java 9)、类型推断的var关键字(Java 10)、单一源文件启动(Java 11)、Switch表达式(Java 12)、Text Block(Java 13)、Record类型(Java 14)和密封的类(Java 15)。这些特性显著提高了Java的易用性和效率。
摘要由CSDN通过智能技术生成

函数式编程(Java 8)
在Java8中,功能编程和lambda被添加为语言功能。函数式编程可与Java中的Streamsnull安全monads(Optional)一起使用,如下所示:

流(Java 8)
对于一般的计算机程序,通常必须使用值列表,并对每个值执行给定的转换。在Java 8之前,您必须使用for循环进行此转换,但是从现在开始,您可以使用Streams以下方法:

Stream.of("hello", "great")
    .map(s -> s + " world")
    .forEach(System.out::println);

hello world
great world
该map函数以一个lambda作为输入,它将应用于流中的所有元素。

Streams可以在Lists,Sets和Maps(通过转换)上工作。

Optional(Java 8)

Java中的另一个常见问题是Null Pointer Exceptions。因此,Java引入了Optional 这是一个monad,它包装了一个可能为null或不为null的引用。可以通过函数性方式将更新应用于此Optional:

Optional.of(new Random().nextInt(10))
    .filter(i -> i % 2 == 0)
    .map(i -> "number is even: " + i)
    .ifPresent(System.out::println);

number is even: 6
在上面的代码段中,我们创建一个随机数,将其包装在Optional对象中,然后仅打印偶数。

JShell(Java 9)

我们有一个Java的REPL,它的名字叫JShell!简而言之,JShell允许在不编写和编译完整Java类的情况下尝试Java代码段。相反,您可以一次执行一个命令,然后立即看到结果。这是一个简单的例子:

$ <JDK>/bin/jshell
jshell> System.out.println("hello world")
hello world

长期以来,熟悉JavaScript或Python等解释型语言的人们都对REPL感到满意,但到目前为止,Java中缺少此功能。JShell允许定义变量,但也可以定义更复杂的实体,例如多行函数,类和执行循环。而且,JShell支持自动完成,如果您不知道给定Java类提供的确切方法,该功能将非常有用。

不可变集合的工厂方法(Java 9)
ListsJava的简单初始化早已丢失,但现在已经过去了。以前,您必须执行以下操作:

jshell> List<Integer> list = Arrays.asList(1, 2, 3, 4)
list ==> [1, 2, 3, 4]

现在将其简化如下:

jshell> List<Integer> list = List.of(1, 2, 3, 4)
b ==> [1, 2, 3, 4]

List,Set和Mapof(…)存在这种奇特的方法。它们都只用一行简单的代码就创建了一个不变的对象。

使用var(Java 10)进行 类型推断
Java 10引入了新的var关键字,该关键字允许省略变量的类型。

jshell> var x = new HashSet<String>()
x ==> []
 
jshell> x.add("apple")
$1 ==> true

在上面的代码段中,编译器x可以将的类型推断为HashSet。
此功能有助于减少样板代码并提高可读性。但是,它有一些局限性:var只能在方法主体内部使用,并且编译器将在编译时推断类型,因此所有内容仍为静态类型。

单一源文件启动(Java 11)
要运行一个 Java 源代码必须先编译(javac),再运行(java),两步执行动作。而在Java 11中,通过一个 java 命令就直接搞定了,如以下所示:

Main.java:
public class Main {
  public static void main(String[] args) {
    System.out.println("hello world");
  }
}
$ java ./Main.java
hello world

对于仅由一个Java类组成的简单启动程序或实验,此功能更方便实用。

Switch表达式(Java 12)
Java 12为我们带来了Switch表达式。这是该表达式与旧的switch语句有何不同的快速展示。
在老switch语句定义了程序的流程:

jshell> var i = 3
jshell> String s;
jshell> switch(i) {
   ...>     case 1: s = "one"; break;
   ...>     case 2: s = "two"; break;
   ...>     case 3: s = "three"; break;
   ...>     default: s = "unknown number";
   ...> }
jshell> s
s ==> "three"

相反,新的switch表达式返回一个值:

jshell> var i = 3;
jshell> var x = switch(i) {
   ...>     case 1 -> "one";
   ...>     case 2 -> "two";
   ...>     case 3 -> "three";
   ...>     default -> "unknown number";
   ...> };
x ==> "three"

总而言之,旧的switch语句用于程序流,新的switch表达式解析为一个值。
这个新的switch语句是一种映射函数:有一个输入(在上述情况下i),有一个输出(在此x),这实际上是一种模式匹配功能。
需要注意的几件事:
1).我们使用箭头 -> 代替双点
2).不需要 break
3).考虑所有可能的情况时,可以省略默认情况
要在Java 12中启用此功能,请使用 --enable-preview --source 12

Text Block (Java 13)
text block,文本块,是一个多行字符串文字,它避免了对大多数转义序列的需要,以可预测的方式自动格式化字符串,并在需要时让开发人员控制格式。
我们以前从外部copy一段文本串到Java中,会被自动转义,如有一段以下字符串:

<html>
  <body>
      <p>Hello, world</p>
  </body>
</html>

将其复制到Java的字符串中,会展示成以下内容:

"<html>\n"  
"    <body>\n"  
"        <p>Hello, world</p>\n"  
"    </body>\n"  
"</html>\n";

即被自动进行了转义,这样的字符串看起来不是很直观,在JDK 13中,就可以使用以下语法了:

"""
<html>
  <body>
      <p>Hello, world</p>
  </body>
</html>
""";

使用"""作为文本块的开始符合结束符,在其中就可以放置多行的字符串,不需要进行任何转义。看起来就十分清爽了

Record类型(Java 14)
record的出现是为了解决java啰嗦的用来作为数据的承载类(entity层),例如get、set、toString等方法

jshell> record Employee (String name, int age, String department) {}
|  created record Employee
 
jshell> var x = new Employee("Anne", 25, "Legal");
x ==> Employee[name=Anne, age=25, department=Legal]
 
jshell> x.name()
$2 ==> "Anne"

Scala对于案例类具有类似的功能,对于Kotlin具有数据类具有类似的功能。到目前为止,在Java中,许多开发人员都使用Lombok,它提供了许多现在受recordsJava 14启发的功能。

instanceof (Java 14)
Java的早期版本已经包含instanceof关键字,但要检查s类型是否为String,然后再次对其进行强制转换以获取其长度。

Object obj = new String("hello");
if (obj instanceof String) {
  System.out.println("String length: " + ((String)obj).length());
}

现在使用Java 14,编译器可以在instanceof check之后自动推断类型:

Object obj = new String("hello");
if (obj instanceof String mystr) {
  System.out.println("String length: " + mystr.length());
}

密封的类(Java 15)
使用sealed关键字,您可以限制哪些类可以扩展给定的类或接口。这是一个例子:

public sealed interface Fruit permits Apple, Pear {
    String getName();
}
 
public final class Apple implements Fruit {
    public String getName() { return "Apple"; }
}
 
public final class Pear implements Fruit {
    public String getName() { return "Pear"; }
}

这是朝着完全支持的模式匹配的方向迈出的重要一步,在该模式下,您可以像对待枚举一样对待类。此sealed功能与switch前面说明的新表达式很好地结合在一起。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值