Java 9 新特性 (EOL)
生命周期结束时间(EOL): 2018/03/31
官方发布介绍页面:https://openjdk.org/projects/jdk9/
1. 模块系统 (Project Jigsaw)
模块系统允许将代码组织成模块。
module com.example.myapp {
requires java.base;
exports com.example.myapp;
}
2. JShell (交互式编程工具)
什么是交互式编程环境?重点词交互,在这样的编程环境中,你每输入一行代码,环境都会给你一个反馈,这就是交互式的编程环境。这种编程环境并不太适合工程化的复杂性需求,但在一些快速验证、简单计算之类的场景下还是非常好用的。其实交互式编程环境在其他高级语言中很早就有了,而Java直到Java 9才正式推出了这样的工具。
下面就来一起学习下,这个Java中的交互式编程环境JShell。
JShell 是一个交互式的 REPL 工具。REPL 是 Read-Eval-Print Loop 的缩写,表示读取-求值-输出循环。JShell 允许你在命令行中输入 Java 代码,并立即查看结果。
-
启动JShell
打开终端,然后执行命令:jshell,执行效果如下:

-
定义变量和执行计算
在jshell中可以快速的执行计算操作并获得结果,比如这样:

-
定义函数
在jshell中也可以函数来封装操作,比如下面就是一个定义求和函数并调用它的例子:

-
定义类
在jshell中,定义一些简单的类,也是可以实现的,比如:

-
查看帮助命令
关于jshell常用命令,我们可以通过
/help来查看

其它命令请自行查看。
3. 集合工厂方法
集合工厂方法用于创建不可变集合。
List<String> list = List.of("a", "b", "c");
Set<String> set = Set.of("a", "b", "c");
Map<String, String> map = Map.of("key1", "value1", "key2", "value2");
以往我们创建一些不可变集合的时候,通常是这样写的:
// 不可变的Set
Set<String> set = new HashSet<>();
set.add("a");
set.add("b");
set.add("c");
set = Collections.unmodifiableSet(set);
// 不可变的List
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list = Collections.unmodifiableList(list);
Java 8 的写法
Set<String> set = Collections.unmodifiableSet(Stream.of("a", "b", "c").collect(toSet()));
List<Integer> list = Collections.unmodifiableList(Stream.of(1, 2, 3).collect(toList()));
Java 9 的写法
Set<String> set = Set.of("a", "b", "c");
List<Integer> list = List.of(1, 2, 3);
Map<String, String> map = Map.of("a", "1", "b", "2", "c", "3");
Map.of()
Map.of(k1, v1)
Map.of(k1, v1, k2, v2)
Map.of(k1, v1, k2, v2, k3, v3)
...
与asList的区别
看到这里,可能有的人会问了,之前不是对于集合有asXxx这样的方便方法了么?他们有啥区别吗?
这里就以List.of和Arrays.asList为例,给大家列一下它们的异同:
Java 9中推出List.of创建的是不可变集合,而Arrays.asList是可变集合
List.of和Arrays.asList都不允许add和remove元素,但Arrays.asList可以调用set更改值,而List.of不可以,会报java.lang.UnsupportedOperationException异常
List.of中不允许有null值,Arrays.asList中可以有null值
4. 私有接口方法
接口可以包含私有方法。
interface MyInterface {
private void privateMethod() {
System.out.println("Private Method");
}
default void defaultMethod() {
privateMethod();
}
}
class MyClass implements MyInterface {}
MyClass obj = new MyClass();
obj.defaultMethod();
5. 钻石操作符与匿名类
钻石操作符可以用于匿名类。
AbstractList<String> list = new AbstractList<>() {
@Override
public String get(int index) {
return null;
}
@Override
public int size() {
return 0;
}
};
6. Stream API 改进
Stream API 增加了更多的方法。
List<Integer> list = List.of(1, 2, 3, 4, 5);
List<Integer> takeWhileList = list.stream().takeWhile(i -> i < 4).collect(Collectors.toList());
List<Integer> dropWhileList = list.stream().dropWhile(i -> i < 4).collect(Collectors.toList());
7. Optional 类改进
Optional 类增加了更多的方法。
Optional<String> optional = Optional.of("Hello");
optional.ifPresentOrElse(System.out::println, () -> System.out.println("Value is absent"));
8. CompletableFuture 改进
CompletableFuture 增加了更多的方法。
CompletableFuture.supplyAsync(() -> "Hello")
.thenApply(String::toUpperCase)
.thenAccept(System.out::println);
9. Process API 改进
Process API 增加了更多的方法。
ProcessHandle currentProcess = ProcessHandle.current();
System.out.println("PID: " + currentProcess.pid());
10. HTTP/2 客户端
新的 HTTP/2 客户端 API。
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://example.com"))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
11. 多版本兼容 JAR
支持多版本兼容的 JAR 文件。
// 在 JAR 文件中包含不同版本的类文件
META-INF/versions/9/com/example/MyClass.class
12. Stack-Walking API
新的 Stack-Walking API。
StackWalker walker = StackWalker.getInstance();
walker.forEach(frame -> System.out.println(frame.getClassName()));
13. 增强的 @Deprecated 注解
@Deprecated 注解增加了更多的属性。
@Deprecated(since = "9", forRemoval = true)
public void deprecatedMethod() {
// 示例代码
}
14. Try-With-Resources 改进
Try-With-Resources 语句的改进。
BufferedReader reader = new BufferedReader(new FileReader("test.txt"));
try (reader) {
System.out.println(reader.readLine());
}
15. 进程 API 改进
进程 API 增加了更多的方法。
ProcessHandle currentProcess = ProcessHandle.current();
System.out.println("PID: " + currentProcess.pid());