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