引用参考文档链接
- Oracle Java9官方文档
- JDK 9 Release Notes
- Module System Quick-Start Guide
- JDK9迁移指南
- Milling Project Coin
- jlink: The Java Linker
- The Java Shell
写在开头
- 本文仅涉及部分JDK9变更,完整可查看官方文档Standard Edition What’s New in Oracle JDK 9
- 除了模块化,其他改动对日常开发影响不多,可以着重关注模块化和接口私有函数
- 在后续的学习中发现,在模块化后,类似于
ServiceLoader.load
的类加载的方法都有变动,大多数都和模块之间的类可视化有关,如果是从低版本迁移,需要额外注意
模块化系统
案例
ModularDemo
因目前Oracle开放的JDK下载版本仅有8/11/17/18,因此该项目通过JDK18编译JDK9(Project language level设置为9)模拟
工程结构
总结
common
与service
是在 Maven 层面上的子模块,JDK9的模块化主要通过类module-info.java
- 每个工程(模块)仅可有一个
module-info.java
- 对外开放的最小粒度是
package
,无法以类作为最小单位,如果有类不愿对外开放,建议迁移到单独的包中 - 打包后,虽然
common
没有开放intern
包,但是最终common.jar中还是会有intern
中的类 - 如果类不惜那个对外开放,但是其中部分功能还需要对外使用,可以单独在对外开放的包中新建一个类,作为转发调用
- 从初步的使用感觉,目前仅在权限控制方面有明显的作用
maven-compiler-plugin
仅在3.8.0+
才支持module
(可查看ModularDemo/pom.xml
)
jlink
可以自定义Java程序运行时的JRE环境
命令使用
1 | jlink --module-path <modulepath> --add-modules <modules> --limit-modules <modules> --output <path> |
优缺点
- 自定义的JRE环境没有无关的jar包,因此启动内存消耗会少
1
2
3System.out.println("totalMemory:" + Runtime.getRuntime().totalMemory()/ (1024 * 1024));
System.out.println("freeMemory:" + Runtime.getRuntime().freeMemory()/ (1024 * 1024));
System.out.println("maxMemory:" + Runtime.getRuntime().maxMemory()/ (1024 * 1024));1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20(base) MacBook-Pro ModularDemo % ./service/src/main/resources/jre/bin/java -jar service/target/service-1.0-SNAPSHOT.jar
hello
this is private class.
1
2
3
false
totalMemory:512
freeMemory:510
maxMemory:8192
(base) MacBook-Pro ModularDemo % java -jar service/target/service-1.0-SNAPSHOT.jar
hello
this is private class.
1
2
3
false
totalMemory:520
freeMemory:514
maxMemory:8192 - 可以根据应用自定义不同的JRE,而不用将所有 module 对全部应用开放
总结
- 初步感受,该功能在嵌入式领域可以发挥非常重要的作用,在服务器端程序,作用可能没有那么明显
- 最好可以搭配The Modular JDK、Modular Source Code、Modular Run-Time Images一起使用,效果更佳(此处埋坑,以后有时间再回头来研究这三个)
正则^
调整作用范围
将作用到整个表达式,而不是第一个group
案例
1 | Pattern compile = Pattern.compile("[^a-b[c-d]e-f]"); |
try-with-resources
可以在try外部声明变量,将变量名放在try中即可,但是该变量受final or effectively final
规则限制,即在初始化完成后不可再次进行赋值操作;
1 | InputStream in = Files.newInputStream(Paths.get("test.txt")); |
匿名类的泛型推断
1 | public interface InferredType <T>{ |
允许接口定义private方法
1 | public interface PrivateFunc { |
- 可以起到优化重复代码的帮助
_
不可作为变量名
1 | // As of Java 9, '_' is a keyword, and may not be used as an identifier |
@SafeVarargs
1 |
|
Class文件版本号变动至53
编译旧版本范围变动
The javac command no longer supports -source or-target values for releases before 6/1.6. However, older class files are still readable by javac. Source code for an older release can be ported to a newer source level. To generate class files usable by releases older than JDK 6, a javac from a JDK 6, 7, or 8 release family can be used.
JEP 182 documents the policy for retiring old -source and -target options.
JDK9在使用javac编译java文件时,指定java的版本仅支持*1.6+*,不再支持编译到1.5以及更早期的版本
JShell
引用官方原文
Immediate feedback is important when learning a programming language and its APIs. The number one reason schools cite for moving away from Java as a teaching language is that other languages have a “REPL” and have far lower bars to an initial “Hello, world!” program. A Read-Eval-Print Loop (REPL) is an interactive programming tool which loops, continually reading user input, evaluating the input, and printing the value of the input or a description of the state change the input caused. Scala, Ruby, JavaScript, Haskell, Clojure, and Python all have REPLs and all allow small initial programs. JShell adds REPL functionality to the Java platform.
Exploration of coding options is also important for developers prototyping code or investigating a new API. Interactive evaluation is vastly more efficient in this regard than edit/compile/execute and System.out.println.
Without the ceremony of class Foo { public static void main(String[] args) { … } }, learning and exploration is streamlined.
大致含义是降低Java学习的入门门槛,可以更方便的测试API
吐槽:
- 对于习惯了ide的代码提示和代码模板(
code templates
)来说,突然使用jshell
会有些难受