Java9新特性

作者:「Rambabu Posa」,一个具有 11 年丰富开发经验的技术牛人。

英文出处:Java 9 Features with Examples

  • Java 9 REPL (JShell)
  • Factory Methods for Immutable List, Set, Map and Map.Entry
  • Private methods in Interfaces
  • Moduar System - Jigsaw Project
  • Process API Improvements
  • Try With Resources Improvement
  • CompletableFuture API Improvement
  • Reactive Streams
  • Diamond Operator for Anonymous Inner Class
  • Optional Class Improvements
  • Stream API Improvements
  • Enhanced @Deprecated annotation
  • HTTP 2 Client
  • Мulti-Resolution Image API

1、Java 9 REPL (JShell)

Oracle 公司(Java Library 开发者)新引进一个代表 Java Shell 的称之为 “jshell” 或者 REPL(Read Evaluate Print Loop)的新工具。该工具可以被用来执行和测试任何 Java 中的结构,如 class,interface,enum,object,statements 等。使用非常简单。

$ jshell
|  Welcome to JShell -- Version 9.0.1
|  For an introduction type: /help intro

jshell> System.out.println("Hello World!");
Hello World!

我们同样可以定义和执行类的方法

jshell> class Hello {
   ...> public static void sayHello() {
   ...> System.out.print("Hello");
   ...> }
   ...> }
|  created class Hello

jshell> Hello.sayHello()
Hello

想要了解更多的功能的话可以执行"/help",它会告诉你许多你想知道的,另外退出命令是"/exit"。

2、Factory Methods for Immutable List, Set, Map and Map.Entry

Oracle 公司引入一些方便使用的工厂方法,用于创建不可变集合 List,Set,Map 和 Map.Entry 对象。这些高效实用的方法可用来创建空或者非空集合对象。
在 Java SE 8 和更早版本中,我们常用类似 unmodifiableXXX 的集合类方法创建不可变集合对象。举个例子,比如我们想创建一个不可变的 List 对象,可能使用到 Collections.unmodifiableList 方法。
然而,这些 Collections.unmodifiableXXX 方法显得非常冗长乏味。为了克服这些缺陷,Oracle 公司给 List、Set 和 Map 接口分别添加了两个更加实用的方法。
List 和 Set 接口使用 of() 方法创建一个空或者非空的不可变 List 或 Set 对象

List immutableList = List.of();
List immutableList = List.of("one","two","three");
 Map<Integer,String> emptyMap = new HashMap<>();
 Map<Integer,String> immutableEmptyMap = Collections.unmodifiableMap(emptyMap);
jshell> Map emptyImmutableMap = Map.of()
emptyImmutableMap ==> {}
Map<Integer,String> nonemptyMap = new HashMap<>();
 nonemptyMap.put(1,"one")
 nonemptyMap.put(2,"two")
 nonemptyMap.put(3,"three")
 Map<Integer,String> immutableNonEmptyMap = Collections.unmodifiableMap(nonemptyMap);
jshell> Map nonemptyImmutableMap = Map.of(1, "one", 2, "two", 3, "three")
nonemptyImmutableMap ==> {2=two, 3=three, 1=one}
jshell> import static java.util.Map.entry

jshell> Map<Integer,String> nonemptyMap = Map.ofEntries(entry(1,"one"),entry(2,"two"));
nonemptyMap ==> {2=two, 1=one}

3、Private methods in Interfaces

在 Java SE 8 中,我们可以在接口中使用默认或者静态方法提供一些实现方式,但是不能创建私有方法。
为了避免冗余代码和提高重用性,Oracle 公司准备在 Java SE 9 接口中引入私有方法。也就是说从 Java SE 9 开始,我们也能够在接口类中使用 ‘private’ 关键字写私有化方法和私有化静态方法。
接口中的私有方法与 class 类中的私有方法在写法上并无差异,如:

public interface Card{

  private Long createCardID(){
    // Method implementation goes here.
  }

  private static void displayCardDetails(){
    // Method implementation goes here.
  }

}

Java9接口中可以存在的东西:

  1. 常量
  2. Abstract methods
  3. Default methods
  4. Static methods
  5. Private methods
  6. Private Static methods

4、Java9 Module System

Java SE 9 新特性中最大的一个变化就是 Module System。Oracle 公司将引入如下特性:

  • Modular JDK
  • Modular Java Source Code
  • Modular Run-time Images
  • Encapsulate Java Internal APIs
  • Java Platform Module System

Java SE 9 版本之前,我们使用整体的 Jars 来开发基于 Java 语言的应用程序。这种体系架构有许多局限性和缺点。为了避免这些缺陷,Java SE 9 迎来了 Module System。

模块化的优点:

JDK,JRE,JARs都变成了更小的模块,我们可以运用任何我们想要的
易于测试与维护
支持更好的性能
更强的封装
我们无法访问内部非关键的api
模块可以非常安全地隐藏不需要的和内部的细节,我们可以获得更好的安全性。
jdk的对比:


jdk8_jdk9.png

JDK8文件结构:


JDK8

JDK9文件结构:
JDK9

所有的JDK模块以"jdk"开头,所有Java SE规范模块以"java"开头,"java.base"模块是“The Mother of Java 9 Module"。
image

image

image
  • 每个模块有唯一一个名字
  • 每个模块在源文件中都有一些描述
  • 模块描述在一个名为“module-info.java”的源文件中表示,"module-info.java"描述一个模块。
  • 模块描述符是一个Java文件。它不是XML,文本文件或属性文件
  • 按照约定,模块描述符文件放置在模块的顶层目录中
  • 每个模块可以有任意数量的包和类型
  • 一个模块可以依赖于任意数量的模块
java

“module”, “requires”, and “exports”并不是java关键字。

5、Process API Improvements

Java SE 9 迎来一些 Process API 的改进,通过添加一些新的类和方法来优化系统级进程的管控。

Process API 中的两个新接口:

  • java.lang.ProcessHandle
  • java.lang.ProcessHandle.Info
ProcessHandle currentProcess = ProcessHandle.current();
System.out.println("Current Process Id: = " + currentProcess.getPid());

6、Try With Resources Improvement

我们知道,Java SE 7 引入了一个新的异常处理结构:Try-With-Resources,来自动管理资源。这个新的声明结构主要目的是实现“Automatic Better Resource Management”(“自动资源管理”)。
Java SE 9 将对这个声明作出一些改进来避免一些冗长写法,同时提高可读性。

Java SE 7中:
  • 任何资源(预定义的Java API类或用户定义的类)都必须实现Java.lang.autocloseable
  • 资源对象必须引用final或有效的final变量
  • 如果资源已经在try-with-Resource语句之外声明,那么我们应该重新引用局部变量
  • 新创建的本地变量在try-with-resources语句中是有效的
void testARM_Before_Java9() throws IOException{
  BufferedReader reader1 = new BufferedReader(new FileReader("test.txt"));
  try (BufferedReader reader2 = reader1) {
    System.out.println(reader2.readLine());
  }
}
void testARM_Java9() throws IOException{
  BufferedReader reader1 = new BufferedReader(new FileReader("test.txt"));
  try (reader1) {
    System.out.println(reader1.readLine());
  }
}

7、CompletableFuture API Improvement

在 Java SE 9 中,Oracle 公司将改进 CompletableFuture API 来解决一些 Java SE 8 中出现的问题。这些被添加的 API 将用来支持一些延时和超时操作,实用方法和更好的子类化。

Executor exe = CompletableFuture.delayedExecutor(50L, TimeUnit.SECONDS);

这里的 delayedExecutor() 是静态实用方法,用来返回一个在指定延时时间提交任务到默认执行器的新 Executor 对象。

8、Reactive Streams

现在,Reactive Programming 由于其便利性在应用程序开发中变得非常流行。Scala、Play、Akka 等框架已经集成 Reactive Streams 并且受益良多。Oracle 公司也在 Java SE 9 中引入了一个新的 Reactive Streams API。
Java SE 9 Reactive Streams API 是一个发布订阅型框架,使我们能够非常简单地使用 Java 语言就能实现异步的、可拓展的和并行的应用。
Java SE 9 引进下面这些 API 来在基于 Java 语言的应用中开发 Reactive Streams:

  • java.util.concurrent.Flow
  • java.util.concurrent.Flow.Publisher
  • java.util.concurrent.Flow.Subscriber
  • java.util.concurrent.Flow.Processor

9、Diamond Operator for Anonymous Inner Class

我们知道,Java SE 7 引入了一个新的特性:Diamond Operator,来避免冗长代码和提升可读性。然而在 Java SE 8 中,Oracle 公司发现在 Diamond 操作器和匿名内部类的使用中存在一些局限性,后来修复了这些问题并准备将其作为 Java 9 的一部分发布出去

List<String> list = new ArrayList <>(){};

10、Optional Class Improvements

在 Java SE 9 中,Oracle 公司添加了一些新的实用方法到 java.util.Optional 类里面。这里我将使用一些简单的示例来描述其中的一个:stream 方法。
如果一个值出现在给定 Optional 对象中,stream() 方法可以返回包含该值的一个顺序 Stream 对象。否则,将返回一个空 Stream。
stream() 方法已经被添加,并用来在 Optional 对象中使用,如

  • stream()
Stream<Optional> emp = getEmployee(id)
Stream empStream = emp.flatMap(Optional::stream)
  • ifPresentOrElse()
public void ifPresentOrElse(Consumerl<? super Tl> action, Runnable emptyAction)
jshell> Optional<Integer> opt1 = Optional.of(4)
opt1 ==> Optional[4]

jshell> opt1.ifPresentOrElse( x -> System.out.println("Result found: " + x), () -> System.out.println("Not Found."))
Result found: 4

jshell> Optional<Integer> opt2 = Optional.empty()
opt2 ==> Optional.empty

jshell> opt2.ifPresentOrElse( x -> System.out.println("Result found: " + x), () -> System.out.println("Not Found."))
Not Found.
  • or()
public Optional<T> or(Supplier<? extends Optional<? extends T>> supplier)
jshell> Optional<String> opStr = Optional.of("Rams")
opStr ==> Optional[Rams]

jshell> import java.util.function.*

jshell> Supplier<Optional<String>> supStr = () -> Optional.of("No Name")
supStr ==> $Lambda$67/222624801@23faf8f2

jshell> opStr.or(supStr)
$5 ==> Optional[Rams]
jshell> Optional<String> opStr = Optional.empty()
opStr ==> Optional.empty

jshell> Supplier<Optional<String>> supStr = () -> Optional.of("No Name")
supStr ==> $Lambda$67/222624801@23faf8f2

jshell> opStr.or(supStr)
$7 ==> Optional[No Name]

11、Stream API Improvements

在 Java SE 9 中,Oracle 公司添加了四个非常有用的新方法到 java.util.Stream 接口里面。正如 Stream 作为一个接口类,所有这些新的实现方法都是默认方法。其中有两个方法非常重要:dropWhile 和 takeWhile。
如果你熟悉 Scala 语言或者其它函数编程语言的话,你一定知道这些方法。他们在写一些功能样式代码时非常有用。
这个 takeWhile() 方法使用一个断言作为参数,返回给定 Stream 的子集直到断言语句第一次返回 false。如果第一个值不满足断言条件,将返回一个空的 Stream。

  • takeWhile
default Stream<T> takeWhile(Predicate<? super T> predicate)

有序

jshell> Stream<Integer> stream = Stream.of(1,2,3,4,5,6,7,8,9,10)
stream ==> java.util.stream.ReferencePipeline$Head@55d56113

jshell> stream.takeWhile(x -> x < 4).forEach(a -> System.out.println(a))
1
2
3

无序

jshell> Stream<Integer> stream = Stream.of(1,2,4,5,3,6,7,8,9,10)
stream ==> java.util.stream.ReferencePipeline$Head@55d56113

jshell> stream.takeWhile(x -> x < 4).forEach(a -> System.out.println(a))
1
2
  • dropWhile

在Stream API中,dropWhile()方法删除了与断言匹配的最长的前缀元素,并返回其他元素。

default Stream<T> dropWhile(Predicate<? super T> predicate)
jshell> Stream<Integer> stream = Stream.of(1,2,3,4,5,6,7,8,9,10)
stream ==> java.util.stream.ReferencePipeline$Head@55d56113

jshell> stream.dropWhile(x -> x < 4).forEach(a -> System.out.println(a))
4
5
6
7
8
9
10
  • iterate

在 Stream API中,iterate()返回以initialValue(第一个参数)开头的元素流,匹配断言(第二个参数),并使用第三个参数生成下一个元素。

static <T> Stream<T> iterate(T seed, Predicate<? super T> hasNext, UnaryOperator<T> next)
jshell> IntStream.iterate(2, x -> x < 20, x -> x * x).forEach(System.out::println)
2
4
16
jshell> IntStream.iterate(2, x -> x < 20, x -> x * x).forEach(System.out::println)
2
4
16
 Java SE 9's iterate() = Java SE 8's iterate() + Java SE 8's filter()
jshell> IntStream.iterate(2, x -> x * x).filter(x -> x < 20).forEach(System.out::println)
2
4
16
  • ofNullable

在Stream API中,ofNullable()返回包含单个元素的顺序流,如果非空,则返回一个空流。

jshell> Stream<Integer> s = Stream.ofNullable(1)
s ==> java.util.stream.ReferencePipeline$Head@1e965684

jshell> s.forEach(System.out::println)
1

jshell> Stream<Integer> s = Stream.ofNullable(null)
s ==> java.util.stream.ReferencePipeline$Head@3b088d51

jshell> s.forEach(System.out::println)

jshell> 

12、Enhanced @Deprecated annotation

在 Java SE 8 和更早版本上,@Deprecated 注解只是一个没有任何方法的标记类接口。它的作用是标记一个 Java API,可以是 calss,field,method,interface,constructor 等。
注释@Deprecated可以标记Java API。注释@Deprecated有很多种含义,例如它可以表示在不远的将来的某个时间,被标记的API将会被移除。它也可以表示这个API已经被破坏了,并不应该再被使用。它还有其它很多含义。为了提供更多有关@Deprecated的信息,@Deprecated添加了forRemoval元素和since元素。
Java SE 9 中也提供了扫描jar文件的工具jdeprscan。这款工具也可以扫描一个聚合类,这个类使用了Java SE中的已废弃的API元素。 这个工具将会对使用已经编译好的库的应用程序有帮助,这样使用者就不知道这个已经编译好的库中使用了那些已废弃的API。

13、HTTP 2 Client

在 Java SE 9 中,Oracle 公司将发布新的 HTTP 2 Client API 来支持 HTTP/2 协议和 WebSocket 特性。现有的 HTTP Client API 存在很多问题(如支持 HTTP/1.1 协议但是不支持 HTTP/2 协议和 WebSocket,仅仅作用在 Blocking 模式中,并存在大量性能问题),他们正在被使用新的 HTTP 客户端的 HttpURLConnection API 所替代。
Oracle 公司准备在 “java.net.http” 包下引入新的 HTTP 2 Client API。它将同时支持 HTTP/1.1 和 HTTP/2 协议,也同时支持同步(Blocking Mode)和异步模式,支持 WebSocket API 使用中的异步模式。

jshell> import java.net.http.*

jshell> import static java.net.http.HttpRequest.*

jshell> import static java.net.http.HttpResponse.*

jshell> URI uri = new URI("http://rams4java.blogspot.co.uk/2016/05/java-news.html")
uri ==> http://rams4java.blogspot.co.uk/2016/05/java-news.html

jshell> HttpResponse response = HttpRequest.create(uri).body(noBody()).GET().response()
response ==> java.net.http.HttpResponseImpl@79efed2d

jshell> System.out.println("Response was " + response.body(asString()))

14、Мulti-Resolution Image API

在 Java SE 9 中,Oracle 公司将引入一个新的 Мulti-Resolution Image API。这个 API 中比较重要的接口是 MultiResolutionImage,在 java.awt.image 包下可获取到。
MultiResolutionImage 封装不同高度和宽度图片(不同解决方案)到一个集合中,并允许我们按需查询使用

15、Miscellaneous Java 9 Features

  • GC增强
  • 统一的JVM日志
  • HTML5风格的Java帮助文档
  • 保留下划线字符。变量不能被命名为_;
  • 废弃Applet API;
  • javac不再支持Java1.4以及之前的版本;
  • 废弃Java浏览器插件;
  • 栈遍历API–栈遍历API能过滤和迟访问在堆
  • 栈跟踪中的信息
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,656评论 18 139
  • Java9 新特性 翻译自 : https://docs.oracle.com/javase/9/whatsnew...
    deadoggy阅读 1,280评论 0 2
  • 作者介绍 菲比 .吉尔曼 (Phoebe Gilman)生于美国纽约,曾在纽约、以色列和欧洲学习艺术创作,现定居加...
    发芽的梦阅读 3,085评论 0 1
  • 那年夏天 遇见你 齐肩短发女孩 你的笑容灿烂 我们一见如故 那年夏天 遇见你 同桌的你 教我复杂难解的数学题 我们...
    书南Q阅读 320评论 6 9
  • 我在那儿等你, 等你等到天明。 不是夜太短, 是对你的思念,太长…… 就这样,一直等你, 秋风把夏天的汗水,风干……
    小剧在成长阅读 184评论 0 6