语法变更
钻石操作符
在Java8中,匿名内部类不支持使用钻石操作符:
复制 Comparator < String > comparator = new Comparator < String >() {
@ Override
public int compare ( String s1 , String s2) {
return 0 ;
}
};
在Java9中,已经支持匿名内部类泛型推断:
复制 Comparator < String > comparator = new Comparator <>() {
@ Override
public int compare ( String s1 , String s2) {
return 0 ;
}
};
try 语句升级
复制 InputStreamReader isr = new InputStreamReader( new FileInputStream( "d:/aaa.txt" )) ;
OutputStreamWriter osw = new OutputStreamWriter( new FileOutputStream( "d:/aaa.txt" )) ;
try (isr; osw) {
isr . read ();
} catch ( Exception e) {
e . printStrackTrace ();
}
下划线标识符限制
Java8可以单独使用下划线定义变量,而Java9中则不允许了。
复制 String _ = "" ; // Java8 编译通过,Java9报错
API变更
接口中的私有方法
Java9中可以在Interface中定义private方法:
复制 public interface MyInterface {
private int add (){
// xxx
}
}
String底层存储结构
String的存储结构由 char[]
变为了 byte[]
Stream API新增方法
Stream新增四个API方法:
复制 // takeWhile,从头遍历并取出符合条件的集合元素,当遇到不符合的元素就停止处理
// 从头遍历整型集合中的偶数,当遇到一个奇数时,就退出
list . stream () . takeWhile (e -> e % 2 == 0 ) . forEach ( System . out :: println);
// dropWhile,从头遍历并删除符合条件的集合元素,当遇到不符合的元素就停止处理
// 从头遍历整型集合中的偶数并删除这个偶数,当遇到一个奇数时,就退出
list . stream () . dropWhile (e -> e % 2 == 0 ) . forEach ( System . out :: println);
// ofNullable,允许创建Stream时,创建一个仅有一个null值作为元素的Stream
Stream . of ( null ); // 报错
Stream . ofNullable ( null ) // 不报错
// iterate,给定一个种子,指定条件和迭代方式来获取流
// 1.8中已经存在generate和iterate方法
// 随机10个数,然后打印
Stream . generate (Math :: radom) . limit ( 10 ) . forEach (System :: out :: println);
// 生成10个数,从0开始,每个数间隔增加2
Stream . iterate ( 0 , t -> t + 2 ) . limit ( 10 ) . forEach ( System . out :: println);
// java9提供了对iterate的重载,功能与上一行代码类似
Stream . iterate ( 0 , t -> t < 10 , t -> t + 1 ) . forEach ( System . out :: println);
此外,Stream的一些方法实现了与Optional的结合:
复制 Optional < Integer > maxOptional = list . stream () . max ();
// Optional也可以获取到他的Stream
maxOptional . stream ();
InputStream新增API
InputStream新增transferTo
方法,此方法会创建缓冲区使用while循环将inputStream中的内容拷贝到outputStream中:
复制 InputStream in = new FileInputStream( "d:/aaa.txt" ) ;
OutputStream out = new FileOutputStream( "d:/bbb.txt" ) ;
in . transferTo (out);
创建只读集合的方法
复制 // java9之前
// 使用Arrays.asList
List < Integer > list1 = Arrays . asList ( 1 , 2 , 3 );
// 使用Collections 将非只读集合变为只读集合
list = Collections . unmodifiableCollection (list);
// java9创建只读集合
List . of ( 1 , 2 , 3 );
Set . of ( 1 , 2 , 3 );
Map . of (k1 , v1 , k2 , v2 , ... );
JShell
可以运行java片段的shell窗口。支持的主要命令:
模块化
谈到Java9大家往往第一个想到的就是Jigsaw项目(后改名为Modularity)。众所周知,Java已经发展超过20年(95年最初发布),Java和相关生态在不断丰富的同时也越来越暴露出一些问题:
Java运行环境的膨胀和臃肿。每次JVM启动的时候,至少会有30~ 60MB的内存加载,主要原因是JVM需要加载rt.jar ,不管其中的类是否被classloader加载,第一步整个jar都会被JVM加载到内存当中去(而模块化可以根据模块的需要加载程序运行需要的class)
当代码库越来越大,创建复杂,盘根错节的“意大利面条式代码”的几率呈指数级的增长。不同版本的类库交叉依赖导致让人头疼的问题,这些都阻碍了Java 开发和运行效率的提升。
很难真正地对代码进行封装,而系统并没有对不同部分(也就是JAR文件)之间的依赖关系有个明确的概念。每一个公共类都可以被类路径之下任何其它的公共类所访问到,这样就会导致无意中使用了并不想被公开访问的API.
什么是模块化:
模块化是在package外的新的一层,一个src目录只能声明为一个模块
在src根目录建立 module-info.java
,声明module
模块之间的可访问性是所使用的模块和使用模块之间的双向协议,在该文件中可以声明当前模块的依赖,以及当前模块暴露的包
IDEA Jdk9 模块化工程
定义service模块:
复制 module service {
// Service 暴露接口包
exports com.yangsx95.api;
// 依赖java的sql包
requires java.sql;
}
定义api模块,依赖service模块:
复制 module api {
// 暴露api包下的所有类,但是不包括子包,比如`com.yangsx95.api.impl`包
exports com.yangsx95.api;
// 依赖service模块
requires service;
}
Maven + Jdk9 模块化工程
Maven 本身对模块化的支持已经非常好了,引入java模块化,主要是对包中的类进一步进行访问权限控制。