此前,Java 的新版本很少出现,而且出现的时间也很延迟。现在,Oracle成功地保持了自己设定的“每六个月推出新 Java”的节奏。所以几天前,严格按照计划,我们终于收到了Java SE 11和JDK(Java 开发工具包) 的实现。与往常一样,新版本将与旧版本兼容,并且对 Java 11 的支持将不早于 2026 年 12 月结束。
Java SE 11 中的新功能(开发人员可见)
回想一下,在 Java 中,更改是通过实施 JEP“JDK 增强提案”而进行的。JEP是一项改进 OpenJDK 的提案,可能会被批准、延迟或拒绝。也就是说,本质上,JEP 的集合是 OpenJDK 的一种开发策略。在新“功能”之前的方括号中,我们将标明相应 JEP 的编号。 [323] Lambda 参数的局部变量语法- lambda 参数的 var 语法 Java 10 引入了 var 关键字,这使得可以不显式指定局部变量的类型。这简化了代码。JEP 323通过 lambda 表达式扩展了此语法的使用。简单的例子:list.stream ()
.map ((var s) -> s.toLowerCase ())
.collect (Collectors.toList ());
正如著名 Java 布道者 Simon Ritter所写,经验丰富的 Java 程序员会注意到,在这种情况下使用 var 可能是不必要的,因为上面的代码可以替换为以下代码:
list.stream ()
.map (s -> s.toLowerCase ())
.collect (Collectors.toList ());
那么为什么要支持 var 呢?只有一种特殊情况 - 当您想要向 lambda 参数添加注释时。如果不涉及某种类型,这是不可能完成的,并且为了避免必须使用显式类型,我们可以使用 var 来简化一切,如下所示:
list.stream ()
.map ((@ Notnull var s) -> s.toLowerCase ())
.collect (Collectors.toList ());
[330] 启动单文件源代码程序 增强 Java 启动器以使用 Java 源代码将程序作为单个文件启动 Java 经常因其冗长的语法和启动(即使是一个简单的应用程序)的多步骤“仪式”而受到批评。有时这会吓跑新手。编写一个仅打印“ Hello World! ”的应用程序 ”,您需要编写一个具有公共静态void
main 方法的类并使用System.out.println
. 完成此操作后,您必须使用javac编译代码。最后,在此之后,您可以启动应用程序,它将显示不幸的问候语(当然,集成开发环境,无论是IDEA还是JavaRush内置的环境,都会自行执行这一“应用程序启动魔法” - 编者注)。老实说:在大多数编程语言中,运行程序的实际脚本看起来要简单得多。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
[321] HTTP 客户端(标准) - HTTP 客户端 API 支持已标准化。JDK 9 引入了新的API来支持HTTP 客户端协议 (JEP 110)。由于 JDK 9 还引入了Java 平台模块系统 (JPMS) ,因此该 API 被作为孵化器模块包含在内(这些模块为开发人员提供尚未成为 Java SE 标准的新 API,而“实时”API 正在开发中)准备删除 - 开发人员可以尝试新的 API 并尝试提供反馈)。一旦进行了必要的更改(该 API 已在 JDK 10 中更新),该 API 就可以成为标准的一部分。因此,HTTP Client API 现已正式包含在 Java SE 11 中。这为JDK引入了一个新的模块和包java.net.http 。主要的新类型有: HttpClient HttpRequest HttpResponse WebSocket 该 API 可以同步或异步使用。在异步模式下,使用CompletionFutures
和CompletionStages
。 [320] 删除 Java EE 和 CORBA 模块随着Java 第九版中引入Java 平台模块系统 (JPMS) ,将整体rt.jar文件拆分为多个模块成为可能。此外,JPMS 允许您创建一个仅包含应用程序所需模块的 Java 运行时环境,从而大大减小其大小。通过透明定义的模块边界,可以更轻松地删除 Java API 的过时部分 - 这就是 JEP 320 所做的。java.se.ee元模块包含六个模块,这些模块不会成为 Java SE 11 标准的一部分,也不会包含在其中在JDK中:
- 科尔巴
- 交易
- 激活
- xml.绑定
- xml.ws
- xml.ws.注释
新API
由于将HTTP Client和Flight Recorder模块纳入语言标准中,JDK 11 中出现了大量新 API 。完整的 API 列表请参见下面由 Gunnar Morling 编译的不同版本 JDK 的综合比较。在本说明中,我们将列出java.net.http、jdk.jfr和java.security模块中未包含的一些新方法。 java.lang.String 可以说是 JDK 11 API 中对 String 最重要的更改之一,有几个有用的新方法。boolean isBlank ()
:如果字符串为空或仅包含空格,则返回 true,否则返回 false。Stream lines()
:返回从此字符串中提取的行流,以行终止符分隔。String repeat (int)
:返回一个字符串,其值是该字符串重复int次的串联。String strip ()
:返回一个字符串,其中第一个非空格字符之前或之后删除了所有空格。String stripLeading ()
:返回删除了第一个非空格字符之前的所有空格的字符串。String stripTrainling ()
:返回一个字符串,其中删除最后一个非空格字符后出现的所有空格。
strip()
该方法已经做了 类似的事情trim ()
,但是通过空间这些方法意味着不同的事情。在这种情况下,trim()
仅空格被截断,并且 in strip()
- 也被截断特殊字符,例如制表符。 java.lang.StringBuffer java.lang.StringBuilder 这两个类都包含一个compareTo ()
接受StringBuffer
/StringBuilder
并返回的新方法int
。词法比较方法与新方法类似compareTo() CharSequence
。 java.io.ByteArrayOutputStream
void writeBytes (byte [])
:将参数的所有字节写入java.io.FileReader输出流
Charset
. java.io.FileWriter 四个新的构造函数允许您指定Charse
t。 java.io.InputStream
io.InputStream nullInputStream ()
:返回InputStream
,不读取任何字节。如何使用这个方法呢?您可以将其视为类似 /dev/null 的东西,以丢弃不需要的输出,或者注入始终返回零字节的输入。
io.OutputStream nullOutputStream ()
io.Reader nullReader ()
io.Writer nullWriter ()
String toString (int)
:这是现有方法的重载,但使用 int 而不是 char。
int compare (CharSequence, CharSequence)
: 按字典顺序比较两个实例CharSequence
。如果第一个序列按字典顺序小于、等于或大于第二个序列,则分别返回负值、零或正值。
lang.Object clone ()
:Java 布道者 Simon Ritter 承认这种方法让他感到困惑。该类
Reference
没有实现接口
Cloneable
,并且该方法将始终抛出异常
CloneNotSupportedException
。不过,专家表示,这种方法将来会有用处。
runFinalizersOnExit ()
已从这两个类中删除,这可能会导致兼容性问题。 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)
int select (java.util.function.Consumer, long)
:选择并在相应通道已准备好进行 I/O 操作的按键上执行操作。long 参数是超时。int select (java.util.function.Consumer)
:与上面的方法类似,但没有超时。int selectNow (java.util.function.Consumer)
:与上面的方法类似,只是它是非阻塞的。
String readString (Path)
:将文件中的所有内容读取到字符串中,使用UTF-8编码将字节解码为字符。String readString (Path, Charset)
:与上面的方法类似,但使用 将字节解码为字符Charset
。Path writeString (Path, CharSequence, java.nio.file. OpenOption [])
:如果将字符序列写入CharSequence
文件,这些字符将被编码为字节(使用UTF-8)。Path writeString (Path, CharSequence, java.nio.file. Charset, OpenOption [])
:与上面的方法类似,只是使用 将字符编码为字节Charset
。
- Path(String, String[]):返回路径,转换路径字符串或组合形成路径字符串的字符串序列。
- 路径(net.URI):通过转换URI返回路径。
Object [] toArray (java.util.function.IntFunction)
:返回一个包含该集合中所有元素的数组,使用提供的生成器函数来分发返回的数组。
void forEach (java.util.function.Consumer)
:对每个Iterable元素执行指定的操作,直到所有元素都已处理完毕或该操作引发异常。boolean removeAll (java.util.Collection)
:删除该集合中也包含在指定集合中的所有元素(可选操作)。boolean removeIf (java.util.function.Predicate)
:删除此集合中满足给定谓词的所有元素。boolean retainAll (java.util.Collection)
:仅保留此集合中包含在指定集合中的元素(可选操作)。
long convert (java.time.Duration)
:将给定的持续时间转换为此单位。
Predicate not(Predicate)
:返回一个谓词,它是给定谓词的否定。
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。
Predicate asMatchPredicate ()
:Java 专家 Simon Ritter 认为这里可能隐藏着真正的 JDK 11 API gem。该方法创建一个谓词来检查该模式是否与给定的输入字符串匹配。
int deflate (ByteBuffer)
:压缩输入数据并用压缩数据填充指定缓冲区。int deflate (ByteBuffer, int)
:压缩输入数据并用压缩数据填充指定缓冲区。返回压缩数据的实际量。void setDictionary (ByteBuffer)
:将给定字典设置为在给定缓冲区中压缩为字节。这是现有方法的重载,现在可以接受ByteBuffer
,而不是字节数组。void setInput (ByteBuffer)
:设置要压缩的输入数据。它也是现有方法的重载。
int inflate (ByteBuffer)
:将字节解压到指定的缓冲区中。返回未压缩的实际字节数。void setDictionary (ByteBuffer)
:将给定字典设置为给定缓冲区中的字节。是现有方法的重载形式。void setInput (ByteBuffer)
:设置解压的输入数据。现有方法的重载形式。
void addAll (Collection)
:添加集合中存在的所有元素。void addAll (int, Collection)
:添加集合中存在的所有元素,从指定索引开始。
int [] getSelectedIndices ()
:按升序返回所选模型中所有所选索引的数组。int getSelectedItemsCount ()
:返回所选项目的数量。
shell.JShellException getCause ()
:返回此 EvalException 所呈现的执行客户端中的可抛出原因,如果原因不存在或未知,则返回 null。
Java 11 的非开发人员功能
[181]基于嵌套的访问控制 Java等语言通过内部类支持嵌套类。为此,编译器必须执行某些技巧。例如: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());
}
}
尽管逻辑上内部类与外部类是同一代码的一部分,但它被编译为单独的类。因此,此操作需要一个合成连接方法,该方法必须由编译器创建,以提供对外部类的私有字段的访问。此 JEP 引入了巢的概念,其中同一巢的两个成员(在我们的示例中为外部和内部)是筑巢伙伴。为类文件格式定义了两个新属性:NestHost和NestMembers。这些更改对于支持嵌套类和字节码的其他语言很有用。此函数为java.lang.Class引入了三个新方法: Class getNestHost () Class [] getNestMembers () boolean isNestmateOf (Class) [309] 动态类文件常量 此 JEP 描述了类文件格式的扩展,以支持新的类文件格式持久池形式为CONSTANT_Dynamic。动态常量的想法似乎是矛盾的,但本质上你可以将其视为 Java 11 中的最终值。池常量的值不是在编译时设置的(与其他常量不同),而是使用引导程序确定提前期价值的方法。因此该值是动态的,但由于其值仅设置一次,因此它也是恒定的。此功能主要针对开发新语言和编译器的人们,这些语言和编译器将生成字节码和类文件作为输出以在 JVM 上运行。 [315] 改进 Aarch64 Intrinsics 该 JEP 由 Red Hat 社区提出。JVM 现在可以使用 Arm 64 指令集中提供的更多专用指令。特别是,这提高了 、 方法sin ()
和cos ()
java.lang.Mathlog ()
类的性能。 [318] Epsilon:无操作垃圾收集器 与JEP 315一样,您可以感谢 Red Hat 引入了 Epsilon 垃圾收集器。Epsilon 的不同寻常之处在于它实际上并不收集垃圾!创建新对象时,它会根据需要分配内存,但不会回收未注册对象占用的空间。“重点是什么?“, - 你问。事实证明,这个“垃圾收集”有两个用途:
- 首先,该垃圾收集器旨在确保新的 GC 算法根据其性能影响进行评估。这个想法是使用 Epsilon 运行示例应用程序并生成一组指标。启用新的垃圾收集算法,运行相同的测试,然后比较结果。
- 对于非常短的任务(想想云中的无服务器函数),您可以保证不会超出分配给堆的内存。这可以通过消除应用程序代码中的开销(包括收集决定是否运行收集器所需的统计信息)来提高性能。如果堆空间耗尽,JVM 可能会通过以下三种方式之一配置错误:
- 正常的称为
OutOfMemoryError
. - 执行堆重置
- JVM 硬盘发生故障,并且可能正在执行其他任务(例如启动调试器)。
- 正常的称为
- 提供用于将数据作为事件生成和使用的 API
- 提供缓冲机制和二进制数据格式
- 允许自定义和过滤事件
- 为操作系统、JVM HotSpot 和 JDK 库提供事件
GO TO FULL VERSION