JDK11 9+ 新特性新功能(第一部分:开发人员可见功能)

JDK11 90+ 新特性新功能(第一部分:开发人员可见功能)

开发人员可见功能

DK 11非常适合改变编码方式的东西。语言语法有一个小的改动,相当数量的新API,以及运行单文件应用程序而无需使用编译器的能力。此外,现在可以看到删除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 will(在这种情况下)是多余的。我们可以轻松地编写相同的代码:

list.stream()
     .map(s -> s.toLowerCase())
     .collect(Collectors.toList());

为什么要添加  
var 支持呢?答案是针对一种特殊情况,即在您想要为Lambda参数添加注释时。如果没有涉及类型,则无法执行此操作。为了避免使用显式类型,我们可以使用它  
var 来简化事物,因此:

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

此功能需要更改Java语言规范(JLS),具体如下:

  • 第24页:var 特殊标识符的描述  。
  • 页面627-30:Lambda参数
  • 页面636:Lambda表达式的运行时评估
  • 页面746:Lambda语法

JEP 330:启动单文件源代码程序

对Java的一个批评是它的语法可能很冗长,与运行一个简单的应用程序相关的“仪式”可能会使初学者难以接近。要编写一个只打印“Hello World!”的应用程序,它需要您public static void main  使用System.out.println 方法编写一个类  并使用该   方法。完成此操作后,您必须使用javac编译代码。最后,您可以运行应用程序以欢迎进入世界。在大多数脚本语言中执行相同操作  非常  简单快捷。


JEP 330无需编译单个文件应用程序,因此现在您可以键入:

java HelloWorld.java

Java启动程序将识别该文件包含Java源代码,并在执行之前将代码编译为类文件。


放置参数    的源文件的名称正在执行该应用程序时作为参数传递。放置   源文件名之前的参数在编译代码后作为参数传递给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还提供’shebang’支持。为了减少在命令行上甚至提及Java启动程序的需要,这可以包含在源文件的第一行。例如:


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

必须–source 使用要使用的Java版本指定  标志。

JEP 321:HTTP客户端(标准)

JDK 9引入了一个新的API来提供对HTTP客户端协议(JEP 110)的支持。由于JDK 9引入了  Java平台模块系统(JPMS),因此该API作为孵化器模块包含在内  。孵化器模块旨在提供新的API,而不使它们成为Java SE标准的一部分。开发人员可以尝试API并提供反馈。一旦进行了任何必要的更改(此API已在JDK 10中更新),就可以移动API以成为标准的一部分。


HTTP Client API现在是  Java SE 11标准的一部分。这向JDK,java.net.http引入了一个新的模块和包。定义的主要类型是:

  • HttpClient的
  • HttpRequest的
  • 的HttpResponse
  • 的WebSocket

API可以同步或异步使用。异步模式使用  CompletableFutures 和  CompletionStages

JEP 320:删除Java EE和CORBA模块

通过在JDK 9中引入JPMS,可以将单片rt.jar文件划分为多个模块。JPMS的另一个优点是现在可以创建一个仅包含应用程序所需模块的Java运行时,从而大大减小了大小。通过干净定义的模块边界,现在可以更轻松地删除过时的Java API部分。这是JEP的作用; java.se.ee元模块包含六个模块,这些模块将不再是Java SE 11标准的一部分,不包含在JDK中。在受影响的模块有:

  • CORBA
  • 交易
  • 激活
  • xml.bind
  • xml.ws
  • xml.ws.annotation

自JDK 9以来,这些模块已被弃用,默认情况下不包含在编译或运行时中。如果您尝试在JDK 9或JDK 10上编译或运行使用这些模块的API的应用程序,则它们会失败。如果在代码中使用这些模块中的API,则需要将它们作为单独的模块或库提供。从我的演示文稿中询问受众,似乎java.xml模块是JAX-WS,基于SOAP的Web服务支持的一部分,它们将导致大多数问题。

新的API

JDK 11中的许​​多新API都来自HTTP客户端模块,现在它已成为标准的一部分,以及包含Flight Recorder。


有关API更改的完整列表,我建议读者对Gunnar Morling生成的不同JDK版本进行出色的比较,该版本  可在Github上获得。


我在这里列出的是除了java.net.http和jdk.jfr模块之外的所有新方法。我还没有列出java.security模块中的新方法和类,它们非常特定于JEP 324和JEP 329的更改(有六个新类和八个新方法)。


java.io.ByteArrayOutputStream中

  • void writeBytes(byte []):将参数的所有字节写入输出流

java.io.FileReader


两个允许指定Charset的新构造函数。


java.io.FileWriter


四个允许指定Charset的新构造函数。


的java.io.InputStream

  •  io.InputStream nullInputStream():返回不  InputStream 读取任何字节的内容。当你第一次看这个方法(以及那些  OutputStream,  Reader,  和  Writer),你想知道什么用呢。您可以将它们视为/ 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。必须有一个理由将其包含在内,大概是为了将来的某些东西。

java.lang.Runtime 
java.lang.System



这里没有新方法,但值得一提的是,该  runFinalizersOnExit() 方法现已从这两个类中删除(这可能是兼容性问题)。


java.lang.String中


我认为这是JDK 11中新API的亮点之一。这里有几个有用的新方法。

  •  boolean isBlank():如果字符串为空或仅包含空格代码点,则返回true,否则返回false。
  •  Stream lines():返回从此字符串中提取的行的流,由行终止符分隔。
  •  String repeat(int):返回一个字符串,其值是此字符串重复计数次数的串联。
  •  String strip():返回一个字符串,其值为此字符串,删除了所有前导和尾随空格。
  •  String stripLeading():返回一个字符串,其值为此字符串,并删除所有前导空格。
  •  String stripTrainling():返回一个字符串,其值为此字符串,并删除所有尾随空格。

您可能会查看   strip() 并询问“这与现有trim()  方法有何不同  ?”答案是如何定义空白在两者之间有所不同。


java.lang.StringBuffer 
java.lang.StringBuilder



这两个类都有一个新  compareTo() 方法,它接受一个   StringBufferStringBuilder 并返回一个  int。词法比较方法与新compareTo() 方法  相同  CharSequence


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):以原子方式将此键的兴趣集设置为现有兴趣集和给定值的按位交集(“和”)。
  •  int interestOpsOr(int):以原子方式将此键的兴趣集设置为现有兴趣集和给定值的按位联合(“或”)。

java.nio.channels.Selector中

  •  int select(java.util.function.Consumer, long):为相应通道准备好进行I / O操作的键选择并执行操作。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):如上所述,除了使用指定的Charset从字节到字符的解码。
  •  Path writeString(Path, CharSequence, java.nio.file. OpenOption[]:将CharSequence写入文件。使用UTF-8字符集将字符编码为字节。
  •  PathwriteString(Path, CharSequence, java.nio.file. Charset, OpenOption[]:如上所述,除了  Characters 使用指定的Charset编码为字节。

java.nio.file.Path

  •  Path of(String, String[])Path 通过转换路径字符串或连接时形成路径字符串的字符串序列来返回a  。
  •  Path of(net.URI)Path 通过转换URI 返回a  。

java.util.Collection中

  •  Object[] toArray(java.util.function.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)。返回谓词,该谓词是提供的谓词的否定。

这是我在JDK 11中最喜欢的新API之一。例如,您可以转换此代码:

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():我认为这可能是新JDK 11 API中隐藏的宝石。它创建一个谓词,测试此模式是否与给定的输入字符串匹配。

java.util.zip.Deflater中

  •  int deflate(ByteBuffer):压缩输入数据并使用压缩数据填充指定的缓冲区。
  •  int deflate(ByteBuffer, int):压缩输入数据并使用压缩数据填充指定的缓冲区。返回压缩的实际数据字节数。
  •  void setDictionary(ByteBuffer):将压缩的预设字典设置为给定缓冲区中的字节。这是现有方法的重载形式,现在可以接受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():返回由此表示的执行客户端中throwable的包装原因,EvalException 如果原因不存在或未知,则返回  null。

 

JDK11 9+ 新特性新功能(第一部分:开发人员可见功能)

相关文章:

你感兴趣的文章:

标签云: