- 「MoreThanJava」 宣扬的是 「学习,不止 CODE」,本系列 Java 基础教程是自己在结合各方面的知识之后,对 Java 基础的一个总回顾,旨在 「帮助新朋友快速高质量的学习」。
- 当然 不论新老朋友 我相信您都可以 从中获益。如果觉得 「不错」 的朋友,欢迎 「关注 + 留言 + 分享」,文末有完整的获取链接,您的支持是我前进的最大的动力!
特性总览
以下是 Java 9 中的引入的部分新特性。关于 Java 9 新特性更详细的介绍可参考这里。
- REPL(JShell)
- 不可变集合的工厂方法
- 模块系统
- 接口支持私有化
- 钻石操作符升级
- Optional 改进
- Stream API 改进
- 反应式流(Reactive Streams)
- 进程 API
- 升级的 Try-With-Resources
- HTTP / 2
- 多版本兼容 Jar 包
- 其他
- 改进应用安全性能
- 统一 JVM 日志
- G1 设为默认垃圾回收器
- String 底层存储结构更改
- CompletableFuture API 改进
- I/O 流新特性
- JavaScript 引擎 Nashorn 改进
- 标识符增加限制
- 改进的 Javadoc
- 改进的 @Deprectaed 注解
- 多分辨率图像 API
- 变量句柄
- 改进方法句柄(Method Handle)
- 提前编译 AOT
一. Java 9 REPL(JShell)
什么是 REPL 以及为什么引入
REPL,即 Read-Evaluate-Print-Loop 的简称。由于 Scala 语言的特性和优势在小型应用程序到大型应用程序市场大受追捧,于是引来 Oracle 的关注,并尝试将大多数 Scala 功能集成到 Java 中。这在 Java 8 中已经完成一部分,比如 Lambda 表达式。
Scala 的最佳功能之一就是 REPL,这是一个命令行界面和 Scala 解释器,用于执行 Scala 程序。由于并不需要开启额外的 IDE (就是一个命令行),它在减少学习曲线和简化运行测试代码方面有独特的优势。
于是在 Java 9 中引入了 Java REPL,也称为 JShell
。
JShell 基础
打开命令提示符,确保您具有 Java 9 或更高版本,键入 jshell
,然后我们就可以开心的使用了。
下面是简单示范:
wmyskxz:~ wmyskxz$ jshell
| Welcome to JShell -- Version 9
| For an introduction type: /help intro
jshell>
jshell> System.out.println("Hello World");
Hello World
jshell> String str = "Hello JShell!"
str ==> "Hello JShell!"
jshell> str
str ==> "Hello JShell!"
jshell> System.out.println(str)
Hello JShell!
jshell> int counter = 0
counter ==> 0
jshell> counter++
$6 ==> 0
jshell> counter
counter ==> 1
jshell> counter+5
$8 ==> 6
也可以在 Java Shell 中定义和执行类方法:
jshell> class Hello {
...> public static void sayHello() {
...> System.out.print("Hello");
...> }
...> }
| created class Hello
jshell> Hello.sayHello()
Hello
jshell>
Java REPL - 帮助和退出
要获得 jshell
工具的帮助部分,请使用/help
命令。要从 jshell
退出,请使用 /exit
命令 (或者直接使用 Ctrl + D
命令退出)。
jshell> /help
| Type a Java language expression, statement, or declaration.
| Or type one of the following commands:
| /list [<name or id>|-all|-start]
| list the source you have typed
| /edit <name or id>
...
jshell> /exit
| Goodbye
wmyskxz:~ wmyskxz$
二. 不可变集合的工厂方法
Java 9 中增加了一些便捷的工厂方法用于创建 不可变 List、Set、Map 以及 Map.Entry 对象。
在 Java SE 8 和更早的版本中,如果我们要创建一个空的 不可变 或 不可修改 的列表,需要借助 Collections
类的 unmodifiableList()
方法才可以:
List<String> list = new ArrayList<>();
list.add("公众号");
list.add("我没有三颗心脏");
list.add("关注走起来");
List<String> immutableList = Collections.unmodifiableList(list);
可以看到,为了创建一个非空的不可变列表,我们需要经历很多繁琐和冗长的步骤。为了克服这一点,Java 9 在 List
接口中引入了以下有用的重载方法:
static <E> List<E> of(E e1)
static <E> List<E> of(E e1,E e2)
static <E> List<E> of(E e1,E e2,E e3)
static <E> List<E> of(E e1,E e2,E e3,E e4)
static <E> List<E> of(E e1,E e2,E e3,E e4,E e5)
static <E> List<E> of(E e1,E e2,E e3,E e4,E e5,E e6)
static <E> List<E> of(E e1,E e2,E e3,E e4,E e5,E e6,E e7)
static <E> List<E> of(E e1,E e2,E e3,E e4,E e5,E e6,E e7,E e8)
static <E> List<E> of(E e1,E e2,E e3,E e4,E e5,E e6,E e7,E e8,E e9)
static <E> List<E> of(E e1,E e2,E e3,E e4,E e5,E e6,E e7,E e8,E e9,E e10)
以及可变参数数目的方法:
static <E> List<E> of(E... elements)
可以看到 Java 9 前后的对比:
// Java 9 之前
List<String> list = new ArrayList<>();
list.add("公众号");
list.add("我没有三颗心脏");
list.add("关注走起来");
List<String> unmodifiableList = Collections.unmodifiableList(list);
// 或者使用 {
{}} 的形式
List<String> list = new ArrayList<>() {
{
add("公众号");
add("我没有三颗心脏");
add("关注走起来");
}};
List<String> unmodifiableList = Collections.unmodifiableList(list);
// Java 9 便捷的工厂方法
List<String> unmodifiableList = List.of("公众号", "我没有三颗心脏", "关注走起来");
(ps: Set、Map 类似,Map 有两组方法:of()
和 ofEntries()
分别用于创建 Immutable Map 对象和 Immutable Map.Entry 对象)
另外 Java 9 可以直接输出集合的内容,在此之前必须遍历集合才能全部获取里面的元素,这是一个很大的改进。
不可变集合的特征
不可变即不可修改。它们通常具有以下几个特征:
1、我们无法添加、修改和删除其元素;
2、如果尝试对它们执行添加/删除/更新操作,将会得到 UnsupportedOperationException
异常,如下所示:
jshell> immutableList.add("Test")
| java.lang.UnsupportedOperationException thrown:
| at ImmutableCollections.uoe (ImmutableCollections.java:68)
| at ImmutableCollections$AbstractImmutableList.add (ImmutableCollections.java:74)
| at (#2:1)
3、不可变集合不允许 null 元素;
4、如果尝试使用 null 元素创建,则会报出 NullPointerException
异常,如下所示:
jshell> List>String> immutableList = List.of("公众号","我没有三颗心脏","关注走起来", null)
| java.lang.NullPointerException thrown:
| at Objects.requireNonNull (Objects.java:221)
| at ImmutableCollections$ListN. (ImmutableCollections.java:179)
| at Lis