Java 9新特性

在这里插入图片描述

一、JDK 和 JRE 目录结构的改变

在这里插入图片描述
在这里插入图片描述

二、模块化系统: Jigsaw -> Modularity

谈到 Java 9 大家往往第一个想到的就是 Jigsaw 项目。众所周知,Java 已经 发展超过 20 年(95 年最初发布),Java 和相关生态在不断丰富的同时也越 来越暴露出一些问题:

  • Java 运行环境的膨胀和臃肿。每次JVM启动的时候,至少会有30~60MB的内存 加载,主要原因是JVM需要加载rt.jar,不管其中的类是否被classloader加载,第 一步整个jar都会被JVM加载到内存当中去(而模块化可以根据模块的需要加载程 序运行需要的class)
  • 当代码库越来越大,创建复杂,盘根错节的“意大利面条式代码”的几率呈指数级的 增长。不同版本的类库交叉依赖导致让人头疼的问题,这些都阻碍了 Java 开发和 运行效率的提升。
  • 很难真正地对代码进行封装, 而系统并没有对不同部分(也就是 JAR 文件)之间 的依赖关系有个明确的概念。每一个公共类都可以被类路径之下任何其它的公共 类所访问到,这样就会导致无意中使用了并不想被公开访问的 API

本质上讲也就是说,用模块来管理各个package,通过声明某个package 暴露,,模块(module)的概念,其实就是package外再裹一层,不声明默 认就是隐藏。因此,模块化使得代码组织上更安全,因为它可以指定哪 些部分可以暴露,哪些部分隐藏
实现目标

  • 模块化的主要目的在于减少内存的开销
  • 只须必要模块,而非全部jdk模块,可简化各种类库和大型应用的开 发和维护
  • 改进 Java SE 平台,使其可以适应不同大小的计算设备 -改进其安全性,可维护性,提高性能
    在这里插入图片描述
    举例:
  • 要想在java9demo模块中调用java9test模块下包中的结构,需要在java9test 的module-info.java中声明
module java9test { 
//package we export exports com.atguigui.bean; 
}

exports: 控制着哪些包可以被其它模块访问到。所有不被导出的包默认 都被封装在模块里面

  • 对应在java 9demo 模块的src 下创建module-info.java文件:
module java9demo { 
	requires java9test;
}

requires: 指明对其它模块的依赖。

三、Java的REPL工具: jShell命令

1.产生背景
像Python 和 Scala 之类的语言早就有交互式编程环境 REPL (read - evaluate - print loop) 了,以交互式的方式对语句和表达式进行求值。开发者只需要输入一些代码, 就可以在编译前获得对程序的反馈。而之前的Java版本要想执行代码,必须创建文 件、声明类、提供测试方法方可实现。

2.设计理念
即写即得、快速运行

3.实现目标

  • Java 9 中终于拥有了 REPL工具:jShell。让Java可以像脚本语言一样运行,从 控制台启动jShell,利用jShell在没有创建类的情况下直接声明变量,计算表达式, 执行语句。即开发时可以在命令行里直接运行Java的代码,而无需创建Java文 件,无需跟人解释”public static void main(String[] args)”这句废话。
  • Shell也可以从文件中加载语句或者将语句保存到文件中。
  • jShell也可以是tab键进行自动补全和自动添加分号
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

四、语法改进:接口的私有方法

  • Java 8中规定接口中的方法除了抽象方法之外,还可以定义静态方法 和默认的方法。一定程度上,扩展了接口的功能,此时的接口更像是 一个抽象类。
  • Java 9中,接口更加的灵活和强大,连方法的访问权限修饰符都可 以声明为private的了,此时方法将不会成为你对外暴露的API的一部分
    在这里插入图片描述
    在这里插入图片描述

五、语法改进:钻石操作符使用升级

我们将能够与匿名实现类共同使用钻石操作符(diamond operator) 在Java 8 中如下的操作是会报错的,Java 9中如下操作可以正常执行通过

Comparator<Object> com = new Comparator<>(){
	@Override public int compare(Object o1, Object o2) { 
		return 0; 
	}
};

编译报错信息:Cannot use “<>” with anonymous inner classes.

六、语法改进:try语句

Java 8 中,可以实现资源的 自动关闭 ,但是要求执行后必须关闭的所有资源必 须在try子句中初始化,否则编译不通过。如下例所示

try(InputStreamReader reader = new InputStreamReader(System.in){ 
//读取数据细节省略 
}catch (IOException e){ 
	e.printStackTrace(); 
}

Java 9 中,用资源语句编写try将更容易,我们可以在try子句中使用已经初始 化过的资源,此时的资源是final的

InputStreamReader reader = new InputStreamReader(System.in); 
OutputStreamWriter writer = new OutputStreamWriter(System.out); 
try (reader; writer) {
 //reader是final的,不可再被赋值 
 //reader = null; 
 //具体读写操作省略 
 } catch (IOException e) {
 	 e.printStackTrace(); 
 }

七、String存储结构变更

结论:String 再也不用 char[] 来存储啦,改成了 byte[] 加上编码标记,节约 了一些空间

public final class String implements java.io.Serializable, Comparable<String>, CharSequence { 
	@Stable 
	private final byte[] value; 
}

那StringBuffer 和 StringBuilder 是否仍无动于衷呢?
String-related classes such as AbstractStringBuilder, StringBuilder, and StringBuffer will be updated to use the same representation, as will the HotSpot VM‘s intrinsic(固有的、内置的) string operations.

八、集合工厂方法:快速创建只读集合

要创建一个只读、不可改变的集合,必须构造和分配它,然后添加元素,最后 包装成一个不可修改的集合

List<String> namesList = new ArrayList <>(); 
namesList.add("Joe"); 
namesList.add("Bob"); 
namesList.add("Bill");
namesList = Collections.unmodifiableList(namesList); 
System.out.println(namesList);

缺点:我们一下写了五行。即:它不能表达为单个表达式

List<String> list = Collections.unmodifiableList(Arrays.asList("a", "b", "c")); 
Set<String> set = Collections.unmodifiableSet(new HashSet<>(Arrays.asList("a", "b", "c"))); 
// 如下操作不适用于jdk 8 及之前版本,适用于jdk 9 Map<String, 
Integer> map = Collections.unmodifiableMap(new HashMap<>() { 
{ 
	put("a", 1); 
	put("b", 2); 
	put("c", 3); 
	} 
}); 
	map.forEach((k, v) -> System.out.println(k + ":" + v));

List firsnamesList = List.of(“Joe”,”Bob”,”Bill”); 调用集合中静态方法of(),可以将不同数量的参数传输到此工厂方法中。此功能 可用于Set和List,也可用于Map的类似形式。此时得到的集合,是不可变的:在 创建后,继续添加元素到这些集合会导致 “UnsupportedOperationException” 。 由于Java 8中接口方法的实现,可以直接在List,Set和Map的接口内定义这些方法, 便于调用

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 加强

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(); 
 }

十、增强的 Stream API

  • Java 的 Steam API 是java标准库最好的改进之一,让开发者能够快速运算, 从而能够有效的利用数据并行计算。Java 8 提供的 Steam 能够利用多核架构 实现声明式的数据处理。
  • 在 Java 9 中,Stream API 变得更好,Stream 接口中添加了 4 个新的方法: takeWhile, dropWhile, ofNullable,还有个 iterate 方法的新重载方法,可以 让你提供一个 Predicate (判断条件)来指定什么时候结束迭代。
  • 除了对 Stream 本身的扩展,Optional 和 Stream 之间的结合也得到了改进。 现在可以通过 Optional 的新方法 stream() 将一个 Optional 对象转换为一个 (可能是空的) Stream 对象

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);
System.out.println();
list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8); list.stream().takeWhile(x -> x < 5).forEach(System.out::println);

dropWhile()的使用

dropWhile 的行为与 takeWhile 相反,返回剩余的元素

List<Integer> list = Arrays.asList(45, 43, 76, 87, 42, 77, 90, 73, 67, 88); 
list.stream().dropWhile(x -> x < 50).forEach(System.out::println); S
ystem.out.println(); 
list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8); 
list.stream().dropWhile(x -> x < 5).forEach(System.out::println);

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 
// 不报异常,允许通过 
List<String> list = new ArrayList<>(); 
list.add("AA"); 
list.add(null); 
System.out.println(list.stream().count());// 2 
// 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

iterate()重载的使用

这个 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("Tom"); 
list.add("Jerry"); 
list.add("Tim");
Optional<List<String>> optional = Optional.ofNullable(list); 
Stream<List<String>> stream = optional.stream(); stream.flatMap(x -> x.stream()).forEach(System.out::println);

十二、Javascript引擎升级:Nashorn

  • Nashorn 项目在 JDK 9 中得到改进,它为 Java 提供轻量级的 Javascript 运行时。 Nashorn 项目跟随 Netscape 的 Rhino 项目,目的是为了在 Java 中实现一个高 性能但轻量级的 Javascript 运行时。Nashorn 项目使得 Java 应用能够嵌入 Javascript。它在 JDK 8 中为 Java 提供一个 Javascript 引擎。
  • JDK 9 包含一个用来解析 Nashorn 的 ECMAScript 语法树的 API。这个 API 使得 IDE 和服务端框架不需要依赖 Nashorn 项目的内部实现类,就能够分析 ECMAScript 代码
    在这里插入图片描述
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值