JDK 11 来了
Posted IT技术知识库
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDK 11 来了相关的知识,希望对你有一定的参考价值。
2018年9月25日,Oracle官方博客公布:
JDK 11 Is Released!
JDK 11 中到底与之前版本有什么区别呢?本文中将对JDK 11 中的部分新功能和API进行简单介绍。
JDK 11 可能是我们改变编码方式的一个契机, 语言的语法有一个小小的改动,增加了相当数量的新API,增加了无需编译就运行单Java文件的能力。 此外,还删除java.se.ee聚合器模块(这个可能会影响把现有应用程序迁移到JDK 11)。
JEP 323:Lambda参数的本地变量语法
JDK 10引入了局部变量类型推断(JEP 286)。 这简化了代码,因为您不再需要显式声明局部变量的类型,而是可以使用var。 JEP 323将此语法的使用扩展到Lambda表达式的参数。 这是一个简单的例子:
list.stream() .map((var s) -> s.toLowerCase()) .collect(Collectors.toList()) |
当然,聪明无比的Java程序员会指出Lambda表达式已经有类型推断,因此在这种情况下使用var是多余的。 我们可以轻松地编写相同的代码:
list.stream() .map(s -> s.toLowerCase()) .collect(Collectors.toList()); |
那为什么要添加var支持呢? 原因是添加var是针对一种特殊情况的,即在我们想要为Lambda参数添加注释时。 如果没有涉及类型,则无法执行此操作。 为了避免使用显式类型,我们可以使用var来简化处理,例如下面这种情况:
list.stream() .map((@Notnull var s) -> s.toLowerCase()) .collect(Collectors.toList()); |
JEP 330:执行单文件源代码程序
长久以来Java有一个令人非常讨厌地方就是语法冗长,比如要编写“Hello World!”的程序,我们就需要“public static void main(String... args)”方法编写一个类,并使用“System.out.println”方法。 完成这么多步骤后,我们还必须使用javac编译代码,最后才可以运行应用程序。然而在大多数脚本语言中执行相同操作非常简单快捷。
在JDK 11版本中,遵循JEP 330无需编译单个文件应用程序,因此可以直接使用下面的命令来执行java程序:
java HelloWorld.java |
Java启动程序将识别该文件包含Java源代码,并在执行之前将代码编译为class文件。
在执行应用程序时,将源文件名称后面的参数作为参数传递。 放在源文件名前面的参数在编译代码后作为参数传递给Java启动程序。 这允许在命令行上设置类路径。 与编译器相关的参数(例如类路径)也将传递给javac进行编译。例如:
java -classpath /home/foo/java Hello.java Bonjour |
这条命令相当于下面的两条:
javac -classpath /home/foo/java Hello.java java -classpath /home/foo/java Hello Bonjour |
在JEP 330规范中,还提供了对'shebang'支持。 这样就可以减少在命令行上启动Java程序所需要的输入内容,这可以包含在源文件的第一行。 例如:
#!/usr/bin/java --source 11 public class HelloWorld { ... |
使用“shebang”支持的时候,第一行内容中必须使用-source标志,在该标志后需要给定使用Java的版本
JEP 321:HTTP客户端(标准)
HTTP Client API现在是Java SE 11标准的一部分。 在JDK 11中引入了一个新的package:java.net.http 。 这个包中主要定义了下面几种类型:
HttpClient
HttpRequest
HttpResponse
WebSocket
这一组API可以以同步或异步的方式进行调用。 异步模式调用API的话需要使用CompletableFutures和CompletionStages。
JEP 320:删除Java EE和CORBA模块
在JDK 9中引入了JPMS,可以将rt.jar文件划分为多个模块。 使用JPMS的优点是可以创建一个仅包含应用程序所需模块的Java运行时依赖jar包,从而大大减小了应用程序的大小。 通过干净定义的模块边界,现在可以更轻松地删除过时的Java API部分。在JDK 11 中 java.se.ee元模块包含的六个模块,将不再是Java SE 11标准的一部分,不包含在JDK中。 受影响的模块是:
corba
transaction
activation
xml.bind
xml.ws
xml.ws.annotation
自JDK 9以来,这些模块已被弃用,默认情况下不包含在编译或运行时中。如果我们尝试在JDK 9或JDK 10上编译或运行使用这些模块的API的应用程序,则它们会变异或者运行失败。如果在代码中使用这些模块中的API,则需要将它们作为单独的模块或库提供。需要留意的是,java.xml模块包含在 JAX-WS中,基于SOAP的Web服务依赖与JAX-WS,因此这类应用程序需要单独引入这个模块否则会发生很多问题。
新增API
JDK 11中的许多新API都来自HTTP客户端模块,现在它已成为标准的一部分。包括在了java.net.http、jdk.jfr、java.security,其中java.security中的新增定义在JEP 324和JEP 329中做了列举,包括了六个新类和八个新方法。下面列举了java.net.http、jdk.jfr中的新增API:
java.io.ByteArrayOutputStream
void writeBytes(byte[]): 将参数的所有字节写入输出流
java.io.FileReader
新增了两个允许指定Charset的新构造函数。
java.io.FileWriter
新增了四个允许指定Charset的新构造函数。
java.io.InputStream
io.InputStream nullInputStream()
: 返回不读取任何字节的InputStream。类似于Linux环境中的 /dev/null (空字符设备),我们可以用来丢弃不需要的输出或提供始终返回零字节的输入。
后面三个类的方法也是一样的
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而不是char。 int是Unicode的代码点。
java.lang.CharSequence
int compare(
CharSequence
,CharSequence
): 按字典顺序比较两个CharSequence实例。 如果第一个序列按字典顺序小于,等于或大于第二个序列,则返回负值,零或正值。
java.lang.ref.Reference
lang.Object clone()
:这个方法没有搞清楚,Reference类没有实现Cloneable接口,并且此方法将始终会抛出CloneNotSupportedException。 估计留着以后JDK12用吧?
java.lang.Runtime
java.lang.System
这两个类里面没有新增的方法,但是删除了runFinalizersOnExit()方法.
java.lang.String
这是JDK 11中新API的亮点之一。这里有几个有用的新方法。
boolean isBlank()
: 如果字符串为空或仅包含空格,则返回true,否则返回falseStream lines()
: 返回从此字符串中提取的行的流,由行终止符分隔.String repeat(int)
: 返回一个字符串,其值是此字符串重复计数次数的串联,如果此字符串为空或count为零,则返回空字符串。String strip()
: 返回一个字符串,其值为此字符串,并删除所有前导和尾随空格。注意:
strip()
貌似等同于做了一次 trim(),事实上,trim()删除的是所有取值小于等于'U+0020'的字符,而strip则仅仅指的空格String stripLeading()
: 返回一个字符串,其值为此字符串,并删除所有前导空格。.String stripTrainling()
: 返回一个字符串,其值为此字符串,并删除所有尾随空格。.
java.lang.StringBuffer
java.lang.StringBuilder
这两个类都有一个新的compareTo()方法,以StringBuffer/StringBuilder为参数,并返回一个int值。这个方法与CharSequence中新的compareTo()方法相同。
java.lang.Thread
没有新增其他方法,但删除destroy()和stop(Throwable)方法。 不过没有参数的stop()方法还在,这点觉得怪怪的。
java.nio.ByteBuffer
java.nio.CharBuffer
java.nio.DoubleBuffer
java.nio.FloatBuffer
java.nio.LongBuffer
java.nio.ShortBuffer
这几个类都添加了一个mismatch()方法,通过这个方法可以找到并返回此缓冲区与给定缓冲区之间第一个不匹配的相对索引。
java.nio.channels.SelectionKey
int interestOpsAnd(int)
: 以原子方式将key的兴趣集设置为现有兴趣集和给定值的按位交集(“和”)。对于interestOpsAnd(int)
或interestOpsOr(int)并发调用时,此方法可以保证是原子级别的操作。这个方法可以随时调用,如果在选择操作正在进行时调用此方法,则它对该操作没有影响;下一个选择操作将看到对key兴趣集的更改。int interestOpsOr(int)
: 以原子方式将key的兴趣集设置为现有兴趣集和给定值的按位联合(“或”).
java.nio.channels.Selector
int select(java.util.function.Consumer, long)
: 对相应通道准备好进行I/O操作的key选择并执行操作。 long参数是超时时间。int select(java.util.function.Consumer)
: 同上,但没有超时时间设定。.int selectNow(java.util.function.Consumer)
: 同上,但是它是非阻塞方法
java.nio.file.Files
String readString(Path)
:将文件中的所有内容读入字符串,读取过程中使用UTF-8字符集解码.String readString(Path, Charset)
: 同上,使用给定字符集解码.Path writeString(Path, CharSequence, java.nio.file. OpenOption[]
将CharSequence写入文件。 使用UTF-8字符集进行编码.PathwriteString(Path, CharSequence, java.nio.file. Charset, OpenOption[]
: 同上,使用给定字符集进行编码
java.nio.file.Path
Path of(String, String[])
: 通过转换路径字符串或连接时形成路径字符串的字符串序列来返回Path。Path of(net.URI)
: 通过转换URI返回路径。.
java.util.Collection
Object[] toArray(java.util.function.IntFunction)
: 返回一个包含此collection中所有元素的数组,使用提供的IntFunction
函数来分配返回的数组。
java.util.concurrent.PriorityBlockingQueue
java.util.PriorityQueue
void forEach(java.util.function.Consumer)
: 对Iterable的每个元素执行给定的操作,直到处理完所有元素或操作抛出异常为止。boolean removeAll(java.util.Collection)
: 删除此集合的所有包含在指定的集合中的元素。.boolean removeIf(java.util.function.Predicate)
: 删除此集合中满足给定谓词的所有元素。.boolean retainAll(java.util.Collection)
: 仅保留此集合中包含在指定集合中的元素。.
java.util.concurrent.TimeUnit
long convert(java.time.Duration)
: 将给定的持续时间转换为参数中给定的单位。 .
java.util.function.Predicate
Predicate not(Predicate)
. 返回Objects.equals(Object,Object) 测试两个参数是否相等的结果。
lines.stream() .filter(s -> !s.isBlank()) |
可以改为
lines.stream() .filter(Predicate.not(String::isBlank)) |
而且,如果我们使用静态导入,它将变为:
lines.stream() .filter(not(String::isBlank)) |
java.util.Optional
java.util.OptionalInt
java.util.OptionalDouble
java.util.OptionalLong
boolean isEmpty()
:如果不存在值,则返回true,否则返回false。
java.util.regex.Pattern
Predicate asMatchPredicate()
: 它创建一个谓词,测试此模式是否与给定的输入字符串匹配。
java.util.zip.Deflater
int deflate(ByteBuffer)
: 压缩输入数据并使用压缩数据填充指定的缓冲区。.int deflate(ByteBuffer, int)
:将字节解压缩到指定的缓冲区中。 返回未压缩的实际字节数。void setDictionary(ByteBuffer)
: 将预设字典设置为给定缓冲区中的字节。 重载现有方法。.void setInput(ByteBuffer)
: 设置解压缩的输入数据。重载现有方法。.
java.util.zip.Inflater
int inflate(ByteBuffer)
: 将字节解压缩到指定的缓冲区中。 返回未压缩的实际字节数。.void setDictionary(ByteBuffer)
: 将预设字典设置为给定缓冲区中的字节。 重载现有方法。.void setInput(ByteBuffer)
: 设置解压缩的输入数据。重载现有方法。.
javax.print.attribute.standard.DialogOwner
这是JDK 11中的一个新类,它是一个属性类,用于支持请求打印或页面设置对话框保持置顶显示。
javax.swing.DefaultComboBoxModel
javax.swing.DefaultListModel
void addAll(Collection)
: 添加集合中存在的所有元素。void addAll(int, Collection)
: 从指定的索引开始添加集合中存在的所有元素。.
javax.swing.ListSelectionModel
int[] getSelectedIndices()
: 以递增顺序返回选择模型中所有选定索引的数组。int getSelectedItemsCount()
: 返回所选项的数量。
jdk.jshell.EvalException
jshell.JShellException getCause()
: 返回此EvalException表示的执行客户端中throwable的错误的原因,如果没有异常或者不存在或错误未知,则返回null.
SheBang ([ʃəˈbæŋ]): 这个符号(#!)的名称,叫做"Shebang"或者"Sha-bang" ,通常在Unix系统的脚本中第一行开头中写到,它指明了执行这个脚本文件的解释程序,使用过程中有以下规则:
如果脚本文件中没有#!这一行,那么它执行时会默认用当前Shell去解释这个脚本(即:$SHELL环境变量)。
如果#!之后的解释程序是一个可执行文件,那么执行这个脚本时,它就会把文件名及其参数一起作为参数传给那个解释程序去执行。
如果#!指定的解释程序没有可执行权限,则会报错“bad interpreter: Permission denied”。如果#!指定的解释程序不是一个可执行文件,那么指定的解释程序会被忽略,转而交给当前的SHELL去执行这个脚本;
如果#!指定的解释程序不存在,那么会报错“bad interpreter: No such file or directory”。 注意:#!之后的解释程序,需要写其绝对路径(如:#!/bin/bash),它是不会自动到$PATH中寻找解释器的。
当然,如果你使用"bash test.sh"这样的命令来执行脚本,那么#!这一行将会被忽略掉,解释器当然是用命令行中显式指定的bash。
以上是关于JDK 11 来了的主要内容,如果未能解决你的问题,请参考以下文章
JDK11的新特性你了解了吗?JDK12已经来了!13还远吗?