Java 11 变更

2018-10-17 15:18 #旧文章

开发相关的部分

相关术语 JEP: JDK Enhancement Proposals, JDK 改善提案 JLS: Java Language Specification, Java 语言规范相关资源 Java11 语言规范(JLS)PDF

JEP 323 Lambda 表达式的本地变量支持

在 JDK 10 中引入了一种本地变量类型JEP 286),从此你可以不必显式写出局部变量的类型,可以直接用 var。JEP 323 将这种语法扩展到了 Lambda 表达式中。下面是例子:

list.stream().map((var s) -> s.toLowerCase());

会有人说,原来的 Lambda 表达式已经能不写类型名了,像这样:

list.stream().map(s -> s.toLowerCase());

那为什么还要添加对 var 的支持呢。在某些特殊情况下,如果你想给 Lambda 表达式的参数加标注(annotation)的话,就必须要写类型名了,这时候就可以这样简化:

list.stream().map((@Notnull var s) -> s.toLowerCase());

JLS 相关页码

  • P24:对 var 标识符的描述
  • P627~630:Lambda 表达式参数
  • P636:Lambda 表达式的运行时表现
  • P746:Lambda 表达式

JEP 330 直接运行单文件源文件

对于初学者而言,Java 的一整套编译 - 运行流程太复杂了,容易造成从入门到放弃的情况,在 Java 11 中,你不需要自己编译单文件 Java 程序了:

Terminal window
java HelloWorld.java

Java 启动器会识别出这是一个源文件,然后就会自动将这个源文件编译再运行。

在文件名的参数都会被当作 Java 程序启动时的参数,文件名的参数会被当作 Java 启动器的参数。与编译器相关的参数也会被传给 Java 编译器(如 classpath)。例如

Terminal window
java -classpath /home/foo/java Hello.java Bonjour

等价于

Terminal window
javac -classpath /home/foo/java Hello.java
java -classpath /home/foo/java Hello Bonjour

该提案还提供了 ‘shebang’ 支持,为了减少命令行的输入,在文件的第一行可以这么写:

#!/usr/bin/java --source 11
public class HelloWorld {
....
}

注意必须要用 --source 来指定使用的 Java 语言版本。

JEP 321 标准 HTTP 客户端

JDK9 引入的一套 HTTP 客户端 API 现在已经被加入 Java SE 11 标准了。在 java.net.http 包中引入了新的类和模块。主要的类型有

该 API 可以异步或同步调用。

JEP 320 删除了 Java EE 和 CORBA 模块

六个位于 java.se.ee 下的模块将不再存在于 Java SE 11 标准中,JDK 也不会包含。下面是受影响的模块:

  • corba
  • transaction
  • activation
  • xml.bind
  • xml.wa
  • xml.wa.annotation

这些模块自 JDK9 以来就被标记成过时 @Deprecated,而且在编译 - 运行时都不会被默认包含。

JDK-8060192 Collection 类新增方法

Collection 接口新增了 toArray(IntFunction)方法,这个新方法是 toArray(T[])的重载,这个新方法引入了些许代码不兼容性,在老版本中,coll.toArray(null)会被视为调用默认的 toArray(T[]),而现在会导致编译器无法确定是调用 toArray(T[])还是调用 toArray(IntFunction)这只是对源码的不兼容性,现存的二进制文件不受影响。你只能将 null 显式转化为需要的数组类型,比如 toArray((Object[])null)。需要注意的是根据标准,将 null 作为 toArray 方法的参数会导致 NullPointerException

新 APIs

完整 API 更新列表可以在这里看到。

下面会列出一些比较值得关注的新增 / 改动:

java.io.ByteArrayOutputStream

  • void writeBytes(byte[])将所有字节全部输出

java.io.FileReader

两个新的构造函数,允许指定文件的字符集。

java.io.FileWriter

四个新的构造函数,允许指定文件的字符集。

java.io.InputStream

  • io.InputStream nullInputStream()返回一个没有读取任何数据的 InputStream,详细见 Java doc

java.io.OutputStream

  • io.OutputStream nullOutputStream()

java.io.Reader

  • io.Reader nullReader()

java.io.Writer

  • io.Writer nullWriter()

java.lang.Character

  • String toString(int)这是一个已有函数的重载,返回的是一个 int 型,表示一个 Unicode 的码点。

java.lang.CharSequence

  • int compare(CharSequence, CharSequence)比较两个 CharSequence。

java.lang.Runtimejava.lang.System

runFinalizersOnExit()在这两个类中都被删除了。

java.lang.String

  • boolean isBlank()如果字符串为空或者只有空格返回 true
  • Stream lines()以行尾分隔符为界,返回一个流
  • String repeat(int)将原字符串的重复几次后返回
  • String strip()将原字符串的所有空格删除并返回
  • String stripLeading()将原字符串领头的空格删除并返回
  • String stripTrailing()将原字符串末尾的空格删除并返回

strip()trim()的区别在于他们对空格的定义不同,strip()的定义可以参照 Character.isWhitespace(int)

java.lang.StringBufferjava.lang.StringBuilder

这两个类都新增了一个 compareTo()方法,和 CharSequence 类似。

java.lang.Thread

destroy()stop(Throwable)已被删除。

java.nio.ByteBuffer java.nio.CharBuffer java.nio.DoubleBuffer java.nio.FloatBuffer java.nio.LongBuffer java.nio.ShortBuffer

这些类都新增了 mismatch()方法。

这些 API 看的头疼,改天再继续写吧

开发无关的部分

JEP 181 嵌套类访问控制

Java 支持嵌套类,要使代码能够正确的运行,编译器需要一些 trick。比如:

public class Outer {
private int outerInt;
class Inner {
public void printOuterInt() {
System.out.println("Outer int = " + outerInt);
}
}
}

编译器会修改成下面的样子来编译:

public class Outer {
private int outerInt;
public int access$000() {
return outerInt;
}
}
class Inner$Outer {
Outer outer;
public void printOuterInt() {
System.out.println("Outer int = " + outer.access$000());
}
}

然而从逻辑上来说,内部类应该是外部类的一部分,但它却被编译成了一个单独的类。这么一来就需要编译器生成一个函数来使内部类获得外部类成员的访问权限。

该提案引入了嵌套的一组概念:两个处于同一个嵌套区域(nest)中的成员称为”nestmate”。在上面的例子里就是 OuterInner。在类文件中有两个新的属性:NestHostNestMembers。这个新特性为 java.lang.Class 引入了三个新方法:

  • Class getNestHost()
  • Class[] getNestMembers()
  • boolean isNestmateOf(Class)

新特性同样更新了 Java 虚拟机规范:Java Virtual Machine Specification (JVMS), section 5.4.4, Access Control.

相关信息:Java Nestmate 稳步推进

JEP 309 动态类文件常量

这个提案将引入一种动态常量,这个常量的值不是在编译时确定的,而是在类加载时载入函数动态确定的。

JEP 324 Curve25519 和 Curve448

现有的 elliptic-curve Diffie-HellmanCurve25519Curve448 取代。

JEP 327 Unicode 10

(就是支持 Unicode 10 了,有什么好说的)

JEP 329 ChaCha20 和 Poly1305 加密算法

就是支持了,下一个

JEP 332 TLS 1.3 !!!

为什么我这么激动,可能是因为我们的 Steam 组叫做 TLSv1.3 吧。

JEP 335 废除 Nashorn 脚本引擎

Nashorn 作为一个高性能的 Javascript 引擎在 JDK8 中引入。因为相关 API 的原因将被移除,目前提议使用新引擎 GraalVM。