Java9新特性
Java9新特性主要发生的改变:
1, 模块化系统
2, Java 的REPL工具: jShell
3, 接口中声明私有方法
4, 钻石操作符升级
5, try结构的语法升级
6, String底层存储结构的变更
7, 集合工厂方法创建只读集合
8, InputStream中transferTo()方法
9, StreamAPI新增的4个方法
10,Optional的新方法stream()
11,升级的Nashorn引擎
模块化系统
1,模块将由通常的类和新的模块声明文件(module-info.java)组成。该文件是位于java代码结构的顶层,该模块描述符明确地定义了我们的模块需要什么依赖关系,以及哪些模块被外部使用。在exports子句中未提及的所有包默认情况下将封装在模块中,不能在外部使用。例子如下:
2,要是module-info.java不能创建,请检查jdk的版本,要求jdk9以上的版本
3,要想在Test01模块中调用Test02模块下包中的结构,需要在Test02的module-info.java中声明:
module Test02 {
//exports :控制着哪些包可以被其它模块访问到 。 所有不被导出的包默认都被封装在模块里面
exports bean;
}
4,对应在Test01 模块的src下创建module-info.java文件:
module Test01 {
//requires :指明对其它模块的依赖。
requires Test02;
}
Java 的REPL工具: jShell
像Python 和 Scala 之类的语言早就有交互式编程环境 REPL (read - evaluate - print -loop)了,以交互式的方式对语句和表达式进行求值。开发者只需要输入一些代码,就可以在编译前获得对程序的反馈。而之前的Java版本要想执行代码,必须创建文件、声明类、提供测试方法方可实现。
1,调出 jShell
jshell
2,获取帮助
3,没有受检异常 ( 编译时异常)
4,使用外部代码编辑器来编写Java5,退出
接口中声明私有方法
jdk9中允许接口中定义私有的方法
接口中的静态方法只能由接口自己调用,接口的实现类不能调用接口的静态方法,使用如下:
interface MyInterface {
void normalInterfaceMethod();
default void methodDefault1() {
init();
}
public default void methodDefault2() {
init();
}
// This method is not part of the public API exposed by MyInterface
private void init() {
System.out.println("默认方法中的通用操作");
}
}
class MyInterfaceImpl implements MyInterface {
@Override
public void normalInterfaceMethod() {
System.out.println("实现接口的方法");
}
}
public class MyInterfaceTest {
public static void main(String[] args) {
MyInterfaceImpl impl = new MyInterfaceImpl();
impl.methodDefault1();
// impl.init();//不能调用
}
}
钻石操作符使用升级
1,钻石操作符与匿名内部类在java8中不能共存,在Java9可以
2,我们将能够与匿名实现类共同使用钻石操作符(diamond operator)在Java 8
中如下的操作是会报错的,如下:
//编译报错信息:Cannot use “<>” with anonymous inner classes.在java9中则可以编译通过
Comparator<Object> com = new Comparator<>(){
@Override
public int compare(Object o1, Object o2) {
return 0;
}
};
try结构的语法升级
1,Java 8 中,可以实现资源的自动关闭,但是要求执行后必须关闭的所有资源必须在try子句中初始化,否则编译不通过。如下例所示:
try(InputStreamReader reader = new InputStreamReader(System.in)){
//读取数据细节省略
}catch (IOException e){
e.printStackTrace();
}
2,Java 9 中,用资源语句编写try将更容易,我们可以在try子句中使用已经初始化过的资源,此时的资源是final的:
InputStreamReader reader = new InputStreamReader(System.in);
OutputStreamWriter writer = new OutputStreamWriter(System.out);
try(reader;writer){
//reader是final的,不可再被赋值
//reader = null;
char[] chars = new char[20];
int len;
if((len = reader.read(chars)) != -1){
String str = new String(chars,0,len);
writer.write(str,0,len);
}
}catch (IOException e){
e.printStackTrace();
}
String底层存储结构的变更
String 再也不用 char[] 来存储啦,改成了 byte[] 加上编码标记,节约了一些空间,StringBuffer和StringBuilder也随着改变。
集合工厂方法创建只读集合
1,jdk8要创建一个只读、不可改变的集合,必须构造和分配它,然后添加元素,最后包装成一个不可修改的集合。
List<String> namesList = new ArrayList <>();
namesList.add("Tommey");
namesList.add("Bob");
namesList.add("CC");
namesList = Collections.unmodifiableList(namesList);
System.out.println(namesList);
2,jdk9调用集合中静态方法of(),可以将不同数量的参数传输到此工厂方法中。此功能可用于Set和List,也可用于Map的类似形式。此时得到的集合,是不可变的:在创建后,继续添加元素到这些集合会导致 “UnsupportedOperationException” 。
List<String> list = List.of("a", "b", "c");
Set<String> set = Set.of("a", "b", "c");
Map<String, Integer> map1 = Map.of("Tom", 12, "Jerry", 21, "Lilei", 33, "HanMeimei", 18);
Map<String, Integer> map2 = Map.ofEntries(Map.entry("Tom", 89),Map.entry("Jim", 78), Map.entry("Tim", 98));
InputStream中transferTo()方法
InputStream 终于有了一个非常有用的方法:transferTo,可以用来将数据直接
传输到 OutputStream,使用如下:
ClassLoader cl = this.getClass().getClassLoader();
try (InputStream is = cl.getResourceAsStream("hello.txt");
OutputStream os = new FileOutputStream("src\\hello1.txt")) {
is.transferTo(os); // 把输入流中的所有数据直接自动地复制到输出流中
} catch (IOException e) {
e.printStackTrace();
}
StreamAPI新增的4个方法
Stream 接口中添加了 4 个新的方法:takeWhile, dropWhile, ofNullable,还有个 iterate 方法的新重载方法,可以让你提供一个 Predicate (判断条件)来指定什么时候结束迭代
1,takeWhile() 的使用:
用于从 Stream 中获取一部分数据,接收一个 Predicate 来进行选择。在有序的Stream 中takeWhile 返回从开头开始的尽量多的元素。
List<Integer> list = Arrays.asList(45, 43, 76, 87, 42, 77, 90, 73, 67, 88);
list.stream().takeWhile(x -> x < 50).forEach(System.out::println);//45,43
2,dropWhile()的使用:
dropWhile 的行为与 takeWhile 相反,返回剩余的元素。
list.stream().dropWhile(x -> x < 50).forEach(System.out::println);//76 ,87 ,42 ,77 ,90 ,73 ,67 ,88
3,ofNullable()的使用:
Java 8 中 Stream 不能完全为null,否则会报空指针异常。而 Java 9 中的 ofNullable 方法允许我们创建一个单元素 Stream,可以包含一个非空元素,也可以创建一个空Stream。
// 报NullPointerException
// Stream<Object> stream1 = Stream.of(null);
// System.out.println(stream1.count());
Stream<String> stringStream = Stream.of("AA", "BB", null);
System.out.println(stringStream.count());// 3
// ofNullable():允许值为null
Stream<Object> stream1 = Stream.ofNullable(null);
System.out.println(stream1.count());// 0
Stream<String> stream = Stream.ofNullable("hello world");
System.out.println(stream.count());// 1
4,ofNullable()的使用:
这个 iterate 方法的新重载方法,可以让你提供一个 Predicate (判断条件)来指定什么时候结束迭代。
// 原来的控制终止方式:
Stream.iterate(1, i -> i + 1).limit(10).forEach(System.out::println);
// 现在的终止方式:
Stream.iterate(1, i -> i < 100, i -> i + 1).forEach(System.out::println);
Optional的新方法stream()
Optional类中stream()的使用:
List<String> list = new ArrayList<>();
list.add("Tommey");
list.add("Tom");
Optional<List<String>> optional = Optional.ofNullable(list);
Stream<List<String>> stream = optional.stream();
stream.flatMap(x -> x.stream()).forEach(System.out::println);
升级的Nashorn引擎
Nashorn 项目在 JDK 9 中得到改进,它为 Java 提供轻量级的 Javascript 运行时。 JDK 9 包含一个用来解析 Nashorn 的 ECMAScript 语法树的 API。这个 API 使得IDE 和服务端框架不需要依赖 Nashorn 项目的内部实现类,就能够分析ECMAScript 代码。
还没有评论,来说两句吧...