Java 9新功能特性简介

Java 9虽然从之前的2016-09-22推迟到2017-03-23,但是现在我们可以一窥其一些亮点新功能,亮点在:Jigsaw、工具、HTTP API和语言细节几个方面。

JIGSAW
将模块绑定成一个或多个包,提供比JAR更强的封装性。
允许向下扩展变成运行时的JAR,适合物联网IoT
缺点是没有模块版本。


module com.mysql.jdbc {
// 依赖的模块
requires java.sql;

// 在模块中导出包
exports com.mysql.jdbc;

// Implements service with instance
provides java.sql.Driver with com.mysql.jdbc.Driver;
}

改变了Javac和Java用法,以便使用模块:
javac -mp modulepath ...
java -mp modulepath -m modulename/moduleclass


jlink是可以用来连接一组模块,以及它们的传递依赖关系,创建一个自定义的模块化运行时缩影。

使用模块的ServiceLoader:


public abstract class BillingService {

public static BillingService getInstance() {
// Java SPI to find the instance
ServiceLoader<BillingServiceProvider> sl =
ServiceLoader.load(BillingServiceProvider.class);

// Fetch first provider implementation
Iterator<BillingServiceProvider> it = sl.iterator();

return it.next().buildBillingService();
}

public abstract String takeMoney();
}


module anothermodule {
exports de.exxcellent.anothermodule;
requires de.exxcellent.java9;

// Provide Service instance (SPI with Jigsaw modules)
provides de.exxcellent.java9.jigsaw.spi.BillingServiceProvider
with de.exxcellent.anothermodule.spi.MastercardBillingServiceProvider;
}

编译运行命令汇总:


$ mkdir -p target/module/de.exxcellent.java9
$ mkdir -p target/module/anothermodule

$ javac $(find playground/src/main/java -name "*.java") \
-d target/module/de.exxcellent.java9
$ javac $(find playground-dependent/src/main/java -name
"*.java")\
-d target/module/anothermodule \
-modulepath target/module

$ java -modulepath target/module \
-m anothermodule/de.exxcellent.anothermodule.TestJigsawSPI
Mastercard billed the money!

REPL:Jshell


⋊> ~ jshell
| Welcome to JShell -- Version 9-ea
| For an introduction type: /help intro

jshell> 3 + 4 * 7
$1 ==> 31

jshell> int add(int a, int b) {
...> return a+b;
...> }
| created method add(int,int)

jshell> add(25, $1)
$3 ==> 56

HTML5 Javadoc
通过-html5参数激活;
搜索兼容
Html5 & 更新的Doclet API
提高的DocLint:
-Xdoclint/package:java.*,javax.*

进程控制
能够检查和检测以及杀死Process。


import java.io.IOException;
import static java.lang.System.out;

public class ControlProcess {

/**
* 启动一个进程process, 监听进程中断,检查进程细节,杀死进程
*/

public static void main(String[] args) throws IOException, InterruptedException {
Process sleeper = Runtime.getRuntime().exec(
"sleep 1h");

// 获得 自己的或启动的进行的PIDs
out.println(
"Your pid is " + ProcessHandle.current().getPid());
out.println(
"Started process is " + sleeper.getPid());

ProcessHandle sleeperHandle = ProcessHandle.of(sleeper.getPid())
// Optional
.orElseThrow(IllegalStateException::new);

// 在退出进程做些善后
sleeperHandle.onExit().thenRun(
// CompletableFuture
() -> out.println(
"Sleeper exited")
);

// Get info on process
out.printf(
"[%d] %s - %s\n",
sleeperHandle.getPid(),
sleeperHandle.info().user().orElse(
"unknown"),
sleeperHandle.info().commandLine().orElse(
"none"));

// Kill a process
sleeperHandle.destroy();

// Give exit handler a chance to see the sleeper onExit()
Thread.sleep(99);
}
}

新的Collection


public class ImmutableCollections {

/**
* 快速创建一个不可变集合
* <b>Note:</b> They do not accept {@code null} or duplicate entries (Set/Map)
*/

public static void main(String args[]) {
List<Integer> listOfNumbers = List.of(1, 2, 3, 4, 5
/*, null*/);
out.println(listOfNumbers);

Set<Integer> setOfNumbers = Set.of(1, 2, 3, 4, 5
/*, 1*/);
out.println(setOfNumbers);

Map<String, String> mapOfString = Map.of(
"key1", "value1", "key2", "value2");
out.println(mapOfString);

Map<String, String> moreMapOfString = Map.ofEntries(
Map.entry(
"key1", "value1"),
Map.entry(
"key2", "value2")/*,
Map.entry("key1", "value3")*/

);
out.println(moreMapOfString);
}
}

增强的Deprecated


@Deprecated(since ="1.5", forRemoval = true)

Stream


// All bytes from an InputStream at once
byte[] result = new ByteArrayInputStream(buf)
.readAllBytes();

// 直接重定向InputStream 到 OutputStream
new ByteArrayInputStream(buf)
.transferTo(System.out);

StackWalker


public class StackWalkerExample {

/**
* Easily traverse stackframes.
*/

public static void main(String[] args) {
walkAndFilterStackframe().forEach(out::println);
}

// return class/method only for our classes.
private static List<String> walkAndFilterStackframe() {
return StackWalker.getInstance().walk(s ->
s.map( frame -> frame.getClassName()+
"/"+frame.getMethodName() )
.filter(name -> name.startsWith(
"de.exxcellent"))
.limit(10)
.collect(Collectors.toList())
);
}

}

包名


this.getClass().getPackageName()

HTTP/2支持


/**
* HTTP API 提供异步和同步功能,在异步模型
* 任务会在线程threads (ExecutorService)执行
*/

public static void main(String[] args) throws Exception {
HttpClient.getDefault()
.request(URI.create(
"https://www.exxcellent.de"))
.GET()
.responseAsync()
// CompletableFuture :D
.thenAccept(httpResponse ->
out.println(httpResponse.body(HttpResponse.asString()))
);
Thread.sleep(999);
// Give worker thread some time.
}

性能
提高了竞争锁的性能
隔离代码缓存
更智能的Java编译

交叉编译
Javac -release n
等同于:
javac -source N -target N –bootclasspath rtN.jar ...

Java 9: A short summary & overview over the new fe