从Java8到Java15的所有内容都可以在10分钟内理解清楚
本文是根据Philipp Gysel先生的文章《在十分钟内从Java 8到Java 15》(发布于2021年1月18日)的翻译版本,并获得了作者的许可才进行发布。
从Java8到Java15,只需10分钟就能理解。

从Java 8到Java 15的历程中,有许多好消息。
首先
本文介绍了自Java 7以来新增的出色新功能。从发布于2020年秋的Java 15开始,将逐个版本地看到Java的重大改进点。现在的Java已经完全支持Lambda表达式、函数式编程、通过var进行类型推断、通过简化的构造函数创建不可变集合以及多行字符串。此外,还引入了一些新颖有趣的实验性功能,如数据类(record)和sealed类。最后,将解释高效的Java REPL。
1. 函数式编程(Java 8)
Java 8添加了函数式编程和Lambda表达式作为语言功能。函数式编程的两个核心范式是不变的值和函数的重要性提升。数据通过转换处理的管道流转。它在每个步骤中接收输入,并将其映射到新的输出上。函数式编程可以在Java的Stream和空值安全的单子(Optional)中使用,如下所示。
2. 流(Java 8)
在一般的计算机程序中,经常需要操作值的列表,并对每个值执行所需的转换。在Java 8之前,需要使用for循环来执行这种转换,但从现在开始,可以使用Stream来实现。
Stream.of("hello", "great")
.map(s -> s + " world")
.forEach(System.out::println);
> hello world
> great world
Streams.java 可以被返述为流.java。
map函数接收一个lambda函数作为输入,并将其应用于流中的所有元素。
Stream可以在List、Set、Map上运作(通过转换)。有了Stream,可以几乎不需要循环代码!?
3. Java 8的可选项
在Java中经常遇到的另一个问题是空指针异常。因此,Java引入了Optional。这是一个包装引用的单子,可以处理空值和非空值的情况。要将其升级为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.java 可选.java
在上面的例子中,我们创建了一个随机数,并用Optional对象进行包装,只有在偶数的情况下才输出值。
4. JShell(Java 9)
终于,这就是Java的REPL,JShell!?简单来说,通过使用JShell,您可以在不编译整个Java类的情况下尝试代码片段。只需执行一个命令,即可立即获取结果。以下是一个简单的示例。
$ <JDK>/bin/jshell
jshell> System.out.println("hello world")
hello world
JShell.sh 的中文释义是什么?
擅长JavaScript和Python等解释型语言的人们一直以来都能够享受REPL的乐趣,但是Java以前一直没有这样的功能。有了JShell,不仅可以定义变量,还可以定义更复杂的实体,例如多行函数、类和循环等。此外,JShell还支持自动补全,当不知道特定Java类提供的准确方法时非常方便。
5. 不变集合的工厂方法(Java 9)
在Java中,长时间缺少对List的简单初始化的支持,但这种时代已经结束了。?以前我们必须这样做。
jshell> List<Integer> list = Arrays.asList(1, 2, 3, 4)
list ==> [1, 2, 3, 4]
收集旧的.sh文件。
这被简化为以下形式。
jshell> List<Integer> list = List.of(1, 2, 3, 4)
b ==> [1, 2, 3, 4]
收藏新的.sh
这个很酷的(…)方法可以在List、Set和Map中找到。无论哪一个,都可以通过一行简单的代码创建不可变对象。
6. 基于var的类型推断 (Java 10)
在Java 10中引入了新的var关键字,可以省略变量的类型。
jshell> var x = new HashSet<String>()
x ==> []
jshell> x.add("apple")
$1 ==> true
TypeInference.sh 的原生汉语解释如下:推断类型.sh
在上面的例子中,编译器可以推断出变量x的类型是HashSet。
这个功能很方便,可以减少样板代码并提高可读性。但是它有一些限制。var只能在方法体内使用。编译器在编译时推断类型,所以所有的都是静态类型的。
7. 单个源文件的启动(Java 11)
在过去,如果要编写一个简单的Java程序,我们首先需要使用javac编译该文件,然后才能使用java命令来运行它。但在Java 11中,我们可以通过一个命令来同时执行这两个步骤。
首先,我们要定义一个名为Main.java的单一源文件。
public class Main {
public static void main(String[] args) {
System.out.println("hello world");
}
}
单一源码启动.java
现在,您可以一步完成编译和执行了。
$ java ./Main.java
hello world
单一源启动.sh
对于简单的入门程序或只有一个Java类的测试情况,使用这个功能可以更轻松地启动单个源代码文件。
8. 开关风格(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"
切换旧版本.sh
相比之下,新的Switch类型会返回一个值。
jshell> var i = 3;
jshell> var x = switch(i) {
...> case 1 -> "one";
...> case 2 -> "two";
...> case 3 -> "three";
...> default -> "unknown number";
...> };
x ==> "three"
切换新脚本.sh
请注意,这个新的switch表达式是一种映射函数。它有一个输入(在这里是i)和一个输出(在这里是x)。实际上,它是一种模式匹配功能,可以将Java更好地与函数式编程的原则兼容,并在一定时间内在Scala中也可以使用类似的switch语句。
有几个需要注意的要点。
-
- コロンの代わりに、矢印->を使っています。
-
- breakは必要ありません。
-
- 考え得るすべてのcaseを考慮すれば、defaultは省略できます。
- Java 12でこの機能を有効にするには、–enable-preview -source 12を使用します。
9. 文本多行(Java 13)
你有定义过类似JSON或XML的长多行字符串吗?以前,我们常常将所有内容放在一行中,并使用换行符\n,但是这样会使得字符串难以阅读。从Java 13开始,我们可以使用多行字符串了!?
请告诉我你的名字。
public class Main {
public static void main(String [] args) {
var s = """
{
"recipe": "watermelon smoothie",
"duration": "10 mins",
"items": ["watermelon", "lemon", "parsley"]
}""";
System.out.println(s);
}
}
多行字符串.java
现在让我们尝试以单个文件启动并执行Main方法。
java --enable-preview --source 13 Main.java
{
"recipe": "watermelon smoothie",
"duration": "10 mins",
"items": ["watermelon", "lemon", "parsley"]
}
MultiLineString.sh 可以进行以下的多行字符串操作。
得到的字符串结果跨越多行,引号””保持不变,制表符\t也保留着!
10. Java 14中的数据类record。
在这篇文章中,我最激动的可能是这个新功能。Java终于引入了数据类!这个类通过record关键字声明,自动包含Getter、构造函数、equals方法等。简而言之,可以消除大量的样板代码!??
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"
录音.sh
Scala有一个类似的案例类,Kotlin有数据类。在Java中,许多开发者使用Lombok来提供Java 14的record所影响的大部分功能。请参阅Baeldung的文章以了解更多详细信息。
11. 没有cast的instanceof (Java 14)
instanceof 关键字在Java的早期版本中就已经存在了。
Object obj = new String("hello");
if (obj instanceof String) {
System.out.println("String length: " + ((String)obj).length());
}
InstanceOfOld.java 的实例
遗憾的部分是,首先要确认 obj 是 String 类型,然后重新转换类型并获取其长度。
在Java 14中,编译器自动进行类型推断后进行了instanceof检查。
Object obj = new String("hello");
if (obj instanceof String mystr) {
System.out.println("String length: " + mystr.length());
}
InstanceOfNew.java 的实例
12. 封闭类(Java 15)
使用sealed关键字,可以限制能够扩展指定类和接口的类。
请帮我翻译英文句子:“Can you help me with my homework?”
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"; }
}
封装类.java
这有什么用呢?你知道有多少水果了吧。这是朝着完全支持的模式匹配迈出的重要一步。可以像枚举类型一样处理类。这个sealed功能与前面介绍的新switch表达式非常相配。
附加信息:Java 8及以上版本的许可条款更新
这篇文章的最后一个话题是许可证。你有没有听说过Oracle停止更新Java 8(免费商业版本)的消息?因此,有以下选择。
-
- 新しいOracle JDKバージョンを使用する(Oracleは各リリース後6ヶ月間だけ無料のセキュリティアップデートを提供)。
-
- 自己責任で古いJDKバージョンを使用する。
-
- 古いOpenJDKのJavaバージョンを使用する。これは引き続き、オープンソースコミュニティやサードパーティベンダーからセキュリティアップデートを取得する。
- プレミアムサポートのためOracleに支払う(例:Java 8は2030年までサポート)。
下一项是针对每个JDK的临时Oracle支持期限。

每个JDK版本的Oracle支持计划
Oracle新的许可模式将受到新发布周期的影响。Oracle将每6个月发布一个新的Java版本。这样,Oracle可以更快地改进Java,并通过实验性功能获得更快的反馈,以跟上最新的语言,如Scala、Kotlin和Python。
请查阅此篇文章获取有关许可证的详细信息。
总结
在过去的6年里,Java经历了艰苦的旅程,并发布了8个全新的Java版本!?这些令人惊叹的新功能都有助于使Java成为与其他基于JVM的竞争对手(如Scala和Kotlin)相比具有竞争力的选择。
写这篇文章真的很开心? 谢谢你的阅读? 最近Java的新版本中,你最喜欢的功能是什么?期待听到你的想法!
在DEV.to首次公开发表。
合作翻译
本文得以公开,有赖以下人士的合作。再次表示感谢。
感谢您愿意与我们分享知识!
指定职责:@gracen
翻译职责:@gracen
审计职责:-
公开职责:@gracen
我們期待著您的意見和反饋。
请问这篇文章您觉得如何呢?
– 您希望看到这样的文章
– 您认为哪些地方不错
– 您认为应该这样做更好吗
等等,我们征求您真实的意见。
收到的意见将对提升今后文章的质量有所帮助,欢迎您在评论区留言,不用客气。
我们也接受意见反馈于Twitter上。
期待大家的留言。