Java 8 特性及示例

21 2025 年 4 月 | 阅读 37 分钟

Oracle 于 2014 年 3 月 18 日发布了新版本的 Java,即 Java 8。这是 Java 平台软件开发的一次革命性发布。它包含了对 Java 编程、JVM、工具和库的各种升级。

Java 8 编程语言增强功能

Java 8 为 Java 编程提供了以下功能:

  • Lambda 表达式,
  • 方法引用,
  • 函数式接口,
  • Stream API,
  • 默认方法,
  • Base64 编码解码,
  • 接口中的静态方法,
  • Optional 类,
  • Collectors 类,
  • ForEach() 方法,
  • Nashorn JavaScript 引擎,
  • 并行数组排序,
  • 类型和重复注解,
  • IO 增强,
  • 并发增强,
  • JDBC 增强等。

Lambda 表达式

Lambda 表达式帮助我们以函数式风格编写代码。它提供了一种通过表达式实现 SAM 接口(单个抽象方法)的清晰简洁的方法。它在集合库中非常有用,可以帮助迭代、过滤和提取数据。

欲了解更多信息和示例:点击此处

语法

Lambda 表达式的基本语法是:

  • 参数列表:可以为空,也可以包含一个或多个参数。它表示表达式使用的参数。
  • 箭头符号 (->):它将参数链接到表达式的主体。
  • 主体:包含 Lambda 表达式的表达式和语句。

文件名: LambdaExample.java

输出

Languages which starts with 'J':
Java 
JavaScript

方法引用

Java 8 的方法引用用于引用函数式接口的方法。它是一种紧凑易用的 Lambda 表达式形式。每次使用 Lambda 表达式仅引用一个方法时,都可以用方法引用替换 Lambda 表达式。

欲了解更多信息和示例:点击此处

方法引用类型

Java 中有四种主要的方法引用类型:

1. 静态方法引用:它们引用类中的静态方法。

语法

示例:Math::max 引用 Math 类中的 max 方法。

2. 特定对象的实例方法引用:它们引用类的特定实例的方法。

语法

示例:假设 strString 的一个实例,str::length 引用 strlength 方法。

3. 特定类型的任意对象的实例方法引用:它们引用在调用时提供的实例的方法。

语法

示例:String::toLowerCase 引用运行时确定的 String 实例上的 toLowerCase 方法。

4. 构造方法引用:它们引用类的构造方法。

语法

示例:ArrayList::new 引用 ArrayList 的构造方法。

文件名: MethodReferenceExample.java

输出

Uppercase Words: [JAVA, STREAM, METHOD, REFERENCES]
Printing each word:Java
Stream
Method
References
New List: [Java, Stream, Method, References]
String to Integer: 100

函数式接口

只包含一个抽象方法的接口称为函数式接口。它可以有任意数量的默认方法和静态方法。它也可以声明 Object 类的方法。

函数式接口也称为单个抽象方法接口(SAM 接口)。

欲了解更多信息和示例:点击此处

文件名: FunctionalInterfaceExample.java

输出

Converted Value: 123
Converted String: JAVA

可选

Java 8 引入了一个新类 Optional。它是一个公共的 final 类,用于处理 Java 应用程序中的 NullPointerException。必须导入 java.util 包才能使用此类。它提供方法来检查特定变量是否存在值。

欲了解更多信息和示例:点击此处

文件名: OptionalMain.java

输出

hello, optional!

forEach

Java 提供了一个新的 forEach() 方法来迭代元素。它定义在 Iterable 和 Stream 接口中。

它是 Iterable 接口中定义的默认方法。扩展 Iterable 接口的集合类可以使用 forEach() 方法迭代元素。

此方法接受一个参数,该参数是一个函数式接口。因此,您可以将 lambda 表达式作为参数传递。

欲了解更多信息和示例:点击此处

文件名: ForEachMapExample.java

输出

Key: 1, Value: One
Key: 2, Value: Two
Key: 3, Value: Three
Key: 4, Value: Four

日期/时间 API

Java 自 Java 8 起引入了新的日期和时间 API。java.time 包包含 Java 8 的日期和时间类。

欲了解更多信息和示例:点击此处

API 规范

  • java.time:用于日期、时间、日期时间组合、瞬间、持续时间、周期和时钟的核心类,使用 ISO-8601 系统。
  • java.time.chrono:支持非 ISO 日历系统,具有预定义和自定义的历法。
  • java.time.format:用于格式化和解析日期时间对象。
  • java.time.temporal:用于日期时间操作的高级功能,面向库开发者。
  • java.time.zone:处理时区、偏移量和规则。

文件名: DateTimeApiShortExample.java

输出

Today: 2024-02-13
Future Date: 2024-02-18
Formatted Future Date: 18-02-2024
Parsed Date: 2024-12-25

Java 接口中的静态方法

接口中的静态方法类似于类中的静态方法。它们使用 static 关键字定义,并且可以在不实例化实现接口的类的情况下调用。这些方法属于接口,而不是实现接口的对象。因此,它们为与接口相关的实用方法提供了一个方便的位置。

文件名: ActionExecutor.java

输出

Static Greeting: Welcome!
Overridden Message: Action Completed.

IO 增强

Java 8 对输入/输出 (IO) 和新输入/输出 (NIO) 框架进行了一些增强,主要侧重于提高文件和流处理的易用性和效率。这些增强功能是 java.nio 包的一部分,包括以下值得注意的功能:

用于 IO 的 Stream API 增强

  • list(Path dir):此方法返回一个惰性填充的 Path 对象流,其中每个元素代表指定目录 (dir) 中的目录条目。
  • lines(Path path):此方法从由 path 参数指定的读取文件中的所有行,并将它们作为 Stream<String> 返回。流的每个元素代表文件中的一行文本。
  • find():此方法用于在以提供开始文件为根的文件树中搜索文件。它返回一个包含在搜索过程中找到的文件 Path 对象的流。但是,您没有提供完整的函数签名,因此不清楚此方法的使用方式。
  • lines():此方法返回一个包含 BufferedReader 输入源的所有行的流。流的每个元素代表输入源中的一行文本。此方法对于处理文件或任何其他输入源中的文本数据非常有用。

类型和重复注解

类型注解

类型注解通过允许在类型使用的任何上下文中都使用注解来丰富 Java 的类型系统。此增强功能使开发人员能够向编译器传达更多信息,从而有助于在编译时进行错误检测和预防。例如,为了防止 NullPointerException,可以注解变量声明,以确保它永远不会包含 null 值。

类型注解的进一步示例包括:

确保列表不包含 null 元素

指定列表的元素不能为空

声明数组应只包含非负整数

出于安全目的标记文件为加密

指示连接已打开并且应相应地进行管理

指定在特定条件下(例如除以零)抛出的异常

重复注解

Java 8 引入了重复注解的概念,允许您将相同的注解多次应用于代码中的单个元素。当您需要将相同的注解重复应用于元素以传达多条信息或应用多个设置时,此功能特别有用。

要使用重复注解,Java 需要两个关键部分:

1. 声明一个可重复的注解类型

首先,我们声明 @Review 注解,并使用 @Repeatable 元注解将其标记为可重复。@Repeatable 的值设置为容器注解类型,在本例中为 Reviews。

在此示例中,@Review 注解可以包含审阅者的姓名、审阅日期和评论。

2. 声明包含注解类型

我们定义 Reviews 容器注解。它必须有一个 value 元素,该元素返回一个可重复注解类型的数组 (Review[])。此容器用于保存应用于同一元素的​​所有 @Review 注解。

文件名: EmployeeRoles.java

输出

Role: Developer
Role: Lead
Role: Manager

默认方法

Java 提供了在接口中创建默认方法的机制。在接口中定义并用 default 关键字标记的方法称为默认方法。这些方法是非抽象方法,可以有方法体。

欲了解更多信息和示例:点击此处

文件名: DefaultMethodsExample.java

输出

Brand: Tesla
The car alarm is now on.
The vehicle alarm is now off.

Nashorn JavaScript 引擎

Nashorn JavaScript 引擎

Nashorn 是一个 JavaScript 引擎。它用于在 JVM(Java 虚拟机)上动态执行 JavaScript 代码。Java 提供了一个名为 jjs 的命令行工具,用于执行 JavaScript 代码。

我们可以通过两种方式执行 JavaScript 代码:

  1. 使用 jjs 命令行工具,以及
  2. 将其嵌入到 Java 源代码中。

欲了解更多信息和示例:点击此处

文件名: NashornExample.java

输出

Hello, Nashorn
Result of 10 + 2: 12
Result of sum(10, 15): 25

StringJoiner

Java 在 java.util 包中添加了一个新的 final 类 StringJoiner。它用于构建由分隔符分隔的字符序列。现在,我们可以通过传递逗号(,)、连字符(-)等分隔符来创建字符串。

欲了解更多信息和示例:点击此处

文件名: StringJoinerExample.java

输出

[Apple, Banana, Cherry, Date]

Collectors

Collectors 是一个 final 类,它扩展了 Object 类。它提供了归约操作,例如将元素累积到集合中、根据各种标准对元素进行汇总等。

欲了解更多信息和示例:点击此处

文件名: CollectorsExample.java

输出

Names List: [John, Sara, Mark, Sara, Chris, Paula]
Names Grouped by First Letter: {J=[John], S=[Sara, Sara], M=[Mark], C=[Chris], P=[Paula]}
All Names Joined: John, Sara, Mark, Sara, Chris, Paula
Distinct Names Count: 5

Stream API

Java 8 的 java.util.stream 包包含类、接口和枚举,允许对元素进行函数式操作。它执行惰性计算。因此,它仅在需要时执行。

欲了解更多信息和示例:点击此处

文件名: StreamApiExample.java

输出

[4, 16, 36, 64, 100]

Stream Filter

Java stream 提供了一个 filter() 方法,用于根据给定的谓词过滤流元素。假设您只想获取列表中偶数元素,您可以使用 filter() 方法轻松完成此操作。

此方法接受谓词作为参数,并返回结果元素流。

欲了解更多信息和示例:点击此处

语法

filter 方法接受 Predicate<T> 作为其参数。Predicate<T> 是一个函数式接口,指定了一个返回布尔值的单方法,该方法接受一个类型为 T 的参数。

文件名: StreamFilterExample.java

输出

[John, Jennifer, Jane]

Java Base64 编码和解码

Java 提供了一个 Base64 类来处理加密和解密。您需要在源文件中导入 java.util.Base64 类才能使用其方法。

此类提供三种不同的编码器和解码器,用于对每个级别的加密信息。

欲了解更多信息和示例:点击此处

文件名: Base64Example.java

输出

Encoded String (Basic) : SGVsbG8sIFdvcmxkIQ==
Decoded String : Hello, World!
Encoded String (URL) : SGVsbG8sIFdvcmxkIQ==
Encoded String (MIME) : SGVsbG8sIFdvcmxkIQ==

Java 并行数组排序

Java 在 Arrays 类中提供了一项新功能,用于并行排序数组元素。parallelSort() 方法已添加到 java.util.Arrays 类中,该类使用 JSR 166 Fork/Join 并行公共池来提供数组排序。它是一个重载方法。

欲了解更多信息和示例:点击此处

文件名: ParallelArraySortingExample.java

输出

Original array: [9, 3, 1, 5, 13, 12, 7, 4, 11, 6]
Sorted array: [1, 3, 4, 5, 6, 7, 9, 11, 12, 13]
Original array: [Peach, Apple, Orange, Banana, Grape, Pear]
Sorted array in reverse order: [Pear, Peach, Orange, Grape, Banana, Apple]

JDBC 增强

Java 数据库连接 (JDBC) 是一个 Java API,用于管理连接到数据库、执行查询和命令以及处理从数据库获取的结果集。

JDBC 改进

1) 移除 JDBC-ODBC 桥接器

从 Java 8 开始,已移除 JDBC-ODBC 桥接器,该桥接器允许 JDBC 应用程序通过 ODBC 驱动程序访问数据库。此决定鼓励使用纯 JDBC 驱动程序以提高性能、可靠性并访问现代数据库功能。

2) JDBC 4.2 中的新功能

Java 8 引入了 JDBC 4.2,为 JDBC API 带来了几项重要增强,旨在使数据库交互更加灵活、强大和安全。以下是主要新增功能的简要概述:

1. 添加了 REF_CURSOR 支持

JDBC 4.2 添加了对 SQL REF CURSOR 类型的支持。这使得 JDBC 能够处理数据库存储过程和函数返回的游标类型,从而更轻松地检索复杂的数据结构。

2. 添加了 java.sql.DriverAction 接口

此接口提供了一种机制,供 JDBC 驱动程序在注销驱动程序时执行清理操作。它增强了驱动程序管理,特别是在涉及 JDBC 驱动程序的动态加载和卸载的场景中。

3. DriverManager 类中 deregisterDriver 方法的安全检查

JDBC 4.2 在 DriverManager.deregisterDriver(Driver driver) 方法中引入了安全检查。这确保只有注册驱动程序的调用者才能注销它,从而防止未经授权的注销并提高安全性。

4. 添加了 java.sql.SQLType 接口

此接口作为 JDBC 类型的基类,提供了一种按名称标识 SQL 类型并将其映射到 JDBC Types 的标准方法。这是处理 SQL 类型时面向对象方法的一种发展。

5. 添加了 java.sql.JDBCType 枚举

伴随 SQLType 接口,JDBCType 枚举实现了该接口,提供了 JDBC 类型的便捷枚举。这使得在 JDBC 操作中更清晰、更类型安全地处理 SQL 数据类型。

6. 支持大更新计数

JDBC 4.2 扩展了 API 以支持大更新计数,可适应影响大量行的 SQL 操作,超出 int 所能表示的范围。例如 Statement.getLargeUpdateCount() 和 Statement.executeLargeUpdate() 方法。

7. 对现有接口的更改

一些接口进行了更新,以适应新功能,例如对大更新计数和新的日期时间 API 的支持。这些更改确保 JDBC 保持与最新的 SQL 标准和 Java 功能兼容。

8. RowSet 1.2 增强

JDBC RowSet 1.2 得到增强,提高了其功能和与 JDBC 4.2 功能的集成。这些包括对 java.sql.SQLType 和新的日期时间 API 的更好支持等。

Java JDBC DriverAction

Java 8 JDBC 4.2 中的 java.sql.DriverAction 接口提供了一种机制,供 JDBC 驱动程序在注销时执行清理操作,从而增强了资源管理和安全性。

DriverAction 方法

方法描述
void deregister()由 DriverManager.deregisterDriver(Driver) 调用,以通知 JDBC 驱动程序已注销。此方法应包含释放资源并执行驱动程序注销时所需的任何最终化操作的必要清理逻辑。

Java JDBC SQLType

方法描述
String getName()以 String 形式返回 SQL 类型名称,通常对应于数据库中使用的 SQL 类型名称。
String getVendor()*返回自定义 SQL 类型供应商的名称,适用于特定于某个数据库供应商的类型。
Integer getVendorTypeNumber()返回表示供应商特定 SQL 类型代码的整数值,用于处理数据库特定类型。

Java JDBCType

`JDBCType` 是一个枚举,它为标识通用 SQL 类型(称为 JDBC 类型)提供常量。此枚举扩展了 `java.lang.Enum` 并实现了 `java.sql.SQLType` 接口。

JDBCType 字段

下表显示了 JDBCType 枚举常量及其描述,提供了对它们所代表的通用 SQL 类型的见解:

枚举常量描述
ARRAY表示 SQL 数据库中的值数组。
BIGINT表示大的整数值,通常映射到 64 位整数。
BINARY表示字节数组,用于二进制值。
比特表示单个位值,通常用于 SQL 数据库中的布尔值。
BLOB表示存储为二进制数据集合的二进制大型对象。
BOOLEAN表示布尔值,用于 true/false 数据。
CHAR表示定长字符字符串。
CLOB表示字符大型对象,用于大型文本数据。
DATALINK表示 SQL 数据库外部数据的链接。
DATE表示日期值(年、月、日)。
DECIMAL表示具有固定精度和小数位数的数值。
DISTINCT表示 DISTINCT 类型,这是 SQL 中定义的一个唯一数据类型。
DOUBLE表示双精度浮点数。
FLOAT表示浮点数。
INTEGER表示整数值,通常映射到 32 位整数。
JAVA_OBJECT表示存储在数据库中的 Java 编程语言中的对象。
LONGNVARCHAR表示国家字符集中的长字符串值。
LONGVARBINARY表示用于二进制值的长字节数组。
LONGVARCHAR表示长字符字符串。
NCHAR表示使用国家字符集的定长字符串。
NCLOB表示国家字符的大型对象。
NULL表示 NULL SQL 类型的特殊类型。
NUMERIC表示具有精度和小数位数的数值。
NVARCHAR表示使用国家字符集的可变长度字符串。
OTHER表示数据库特定的、JDBC 未定义的类型。
REAL表示单精度浮点数。
REF表示数据库中 SQL 结构化类型的实例的引用。
REF_CURSOR表示游标或游标的引用。
ROWID表示 SQL 数据库使用的行 ID。
SMALLINT表示小的整数值。
SQLXML表示 SQL XML 值。
STRUCT表示 SQL 结构化类型。
TIME表示时间值(小时、分钟、秒)。
TIME_WITH_TIMEZONE表示带有时区信息的时间值。
TIMESTAMP表示时间戳(日期和时间)。
TIMESTAMP_WITH_TIMEZONE表示带有时区信息的时间戳。
TINYINT表示非常小的整数值。
VARBINARY表示用于二进制的可变字节数组。
VARCHAR表示可变长度字符字符串。

JDBCType 方法

方法描述返回值
getName()返回表示 SQL 数据类型的 SQLType 名称。String
getVendor()返回支持此数据类型的供应商的名称。String
getVendorTypeNumber()返回数据类型的供应商特定类型编号。Integer
valueOf(int type)返回与指定的 java.sql.Types 值对应的 JDBCType。如果此枚举类型没有具有指定 Types 值的常量,则抛出 IllegalArgumentExceptionJDBCType
valueOf(String name)返回此类型中具有指定名称的枚举常量。字符串必须与声明此类型中的枚举常量所使用的标识符完全匹配。如果没有指定名称的常量,则抛出 IllegalArgumentException;如果参数为 null,则抛出 NullPointerExceptionJDBCType
values()返回一个包含此枚举类型的常量的数组,顺序与声明时相同。可以使用此方法迭代常量。JDBCType[]

Java 8 安全性增强

1) Java 安全套接字扩展 (JSSE) 提供程序默认在客户端启用传输层安全 (TLS) 1.1 和 TLS 1.2 协议。

2) 添加了一个改进的方法 AccessController.doPrivileged,它允许代码断言其权限子集,而不会阻止堆栈的完全遍历以检查其他权限。

3) 已将高级加密标准 (AES) 和基于密码的加密 (PBE) 算法(如 PBEWithSHA256AndAES_128 和 PBEWithSHA512AndAES_256)添加到 SunJCE 提供程序。

4) Java 安全套接字扩展 (SunJSSE) 在 JDK 7 中默认启用了服务器名称指示 (SNI) 扩展用于客户端应用程序,而 JDK 8 支持服务器应用程序的 SNI 扩展。SNI 扩展是一项功能,它扩展了 SSL/TLS 协议,用于在握手期间指示客户端尝试连接到哪个服务器名称。

5) 增强了 SunJSSE 以支持带关联数据的认证加密 (AEAD) 算法。增强了 Java Cryptography Extension (SunJCE) 提供程序以支持 AES/GCM/NoPadding 密码实现以及 Galois/Counter Mode (GCM) 算法参数。

6) 向 keytool 工具添加了一个新的命令行标志 -importpassword。它用于接受密码并将其安全地存储为密钥。添加了 java.security.DomainLoadStoreParameter 和 java.security.PKCS12Attribute 等类来支持 DKS 密钥库类型。

7) 在 JDK 8 中,通过 SHA-2 系列消息摘要实现的 SHA-224 变体增强了加密算法。

8) 增强了对 NSA Suite B 加密的支持,包括:

  • NSA Suite B 加密算法的 OID 注册
  • 支持 2048 位 DSA 密钥对生成和 2048 位 DSA 密钥的其他签名算法,如 SHA224withDSA 和 SHA256withDSA。
  • 将 Diffie-Hellman (DH) 算法的密钥长度限制从 1024 位提高到 2048 位。

9) SecureRandom 类提供了用于生成加密强随机数的功能,这些随机数用于私钥或公钥、密码和签名消息。JDK 8 中引入了 getInstanceStrong() 方法,该方法返回最强的 SecureRandom 实例。创建 RSA 私钥和公钥时应使用它。SecureRandom 包括以下其他更改:

  • 为 UNIX 平台引入了两个新实现,它们提供阻塞和非阻塞行为。

10) 包含了一个新的 PKIXRevocationChecker 类,它使用 PKIX 算法检查证书的吊销状态。它支持尽力检查、终端实体证书检查和特定于机制的选项。

11) 公钥加密标准 11 (PKCS) 已扩展到支持 Windows 的 64 位。

12) 为 Kerberos 5 添加了两个新的 rcache 类型。类型 none 表示根本没有 rcache,类型 dfl 表示 DFL 风格的文件类 rcache。此外,现在支持接收方请求的子密钥。它们使用 sun.security.krb5.rcache 和 sun.security.krb5.acceptor.subkey 系统属性进行配置。

13) 在 JDK 8 中,Kerberos 5 协议转换和受限委派在同一域内得到支持。

14) Java 8 默认禁用弱加密。DES 相关的 Kerberos 5 加密类型默认不支持。可以通过在 krb5.conf 文件中添加 allow_weak_crypto=true 来启用这些加密类型。

15) 可以将服务器名称设置为 null 以表示未绑定的服务器。这意味着客户端可以使用任何服务器名称请求服务。建立上下文后,服务器可以检索名称作为协商属性,其键为 SASL.BOUND_SERVER_NAME。

16) 现在 Mac OS X 上支持到本地 Java 通用安全服务 (JGSS) 的 Java Native Interface (JNI) 桥接。可以通过将系统属性 sun.security.jgss.native 设置为 true 来启用它。

17) 定义了一个新的系统属性 jdk.tls.ephemeralDHKeySize 来自定义临时 DH 密钥大小。可接受的最小 DH 密钥大小为 1024 位,导出套件或旧版模式除外 (jdk.tls.ephemeralDHKeySize=legacy)。

18) Java 安全套接字扩展 (JSSE) 提供程序默认遵守客户端的密码套件首选项。但是,可以通过服务器上的 SSLParameters.setUseCipherSuitesOrder(true) 调用来更改行为以尊重服务器的密码套件首选项。


Java 8 工具增强

1) 引入了 jjs 命令,该命令以交互式 shell 模式调用 Nashorn 引擎,或用于解释脚本文件。

2) java 命令能够启动 JavaFX 应用程序,前提是 JavaFX 应用程序已正确打包。

3) java 命令的 man 页(nroff 和 HTML)已完全重做。高级选项现在根据它们影响的区域分为运行时、编译器、垃圾回收和服务性。现在已描述了几个先前缺失的选项。还有一个关于自上一版本以来已弃用或移除的选项的部分。

4) 新的 jdeps 命令行工具允许开发人员分析类文件以确定包级别或类级别的依赖关系。

5) 可以远程访问诊断命令,以前只能通过 jcmd 工具在本地访问。使用 Java 管理扩展 (JMX) 提供远程访问,因此诊断命令会暴露给注册到平台 MBean 服务器的平台 MBean。MBean 是 com.sun.management.DiagnosticCommandMBean 接口。

6) jarsigner 工具包含了一个新的选项 -tsapolicyid,它允许您请求时间戳授权 (Time Stamping Authority) 的签名时间戳并将其附加到签名 JAR 文件。

7) 包含了一个新的方法 java.lang.reflect.Executable.getParameters,它允许您访问任何方法或构造函数的正式参数名称。但是,.class 文件默认不存储正式参数名称。要将正式参数名称存储在特定的 .class 文件中,从而使反射 API 能够检索正式参数名称,请使用 javac 编译器的 -parameters 选项编译源文件。

8) Java 语言规范 (JLS) 第 15.21 部分中二进制比较的类型规则现在将由 javac 正确强制执行。

9) 在此版本中,删除了 apt 工具及其在 com.sun.mirror 包中的关联 API。

Javadoc 增强

在 Java SE 8 中,Javadoc 工具添加了以下新 API:

  • 一个新的 DocTree API 引入了一个扫描器,该扫描器允许您遍历由抽象语法树表示的源代码。这扩展了 Compiler Tree API,提供了对 javadoc 注释内容的结构化访问。
  • javax.tools 包包含类和接口,允许您直接从 Java 应用程序调用 Javadoc 工具,而无需执行新进程。
  • 生成的类或接口文档的“方法摘要”部分已重新组织。此部分中的方法描述按类型分组。默认情况下,会列出所有方法。您可以单击一个选项卡来查看特定类型的方法(静态、实例、抽象、具体或已弃用,如果它们存在于类或接口中)。
  • javadoc 工具现在支持检查 javadoc 注释的内容是否存在可能导致已由 javadoc 生成的文件出现各种问题,例如无效 HTML 或可访问性问题。此功能默认启用,也可以通过新的 -Xdoclint 选项进行控制。

Pack200 增强

由于 JSR 292(支持 Java 平台上的动态类型语言),Java 类文件格式已更新。

Pack200 引擎已更新,以确保 Java SE 8 类文件得到有效压缩。现在,它可以识别 JSR 292 引入的常量池条目和新的字节码。因此,使用此版本的 pack200 工具创建的压缩文件将与旧版本的 unpack200 工具不兼容。


Java 8 IO 增强

在 Java 8 中,对 java.nio.charset.Charset 和扩展的 charset 实现进行了一些改进。包括以下内容:

  • 新的 SelectorProvider,可以提高服务器的性能或可伸缩性。/dev/poll SelectorProvider 仍是默认选项。要使用 Solaris 事件端口机制,请使用系统属性 java.nio.channels.spi.Selector 并将其值设置为 sun.nio.ch.EventPortSelectorProvider。
  • 文件大小 <JDK_HOME>/jre/lib/charsets.jar 已减小。
  • 提高了 java.lang.String(byte[], ∗) 构造函数和 java.lang.String.getBytes() 方法的性能。

Java 8 网络增强

1) 添加了一个新的类 java.net.URLPermission。它表示访问给定 URL 定义的资源的权限。

2) 添加了一个包 jdk.net,其中包含特定于平台的套接字选项以及在所有标准套接字类型上设置这些选项的机制。套接字选项在 jdk.net.ExtendedSocketOptions 中定义。

3) 在 HttpURLConnection 类中,如果安装了安全管理器,并且调用了一个导致尝试打开连接的方法,则调用者必须拥有目标 URL 的“connect”SocketPermission 或允许此请求的 URLPermission。

如果启用了自动重定向,并且此请求被重定向到另一个目标,则调用者还必须拥有连接到重定向主机/ URL 的权限。


Java 8 并发增强

java.util.concurrent 包添加了两个新接口和四个新类。

Java.util.concurrent 接口

Interface描述
public static interface CompletableFuture.AsynchronousCompletionTask它是一个标记接口,用于标识由 async 方法生成的异步任务。它可能有助于监控、调试和跟踪异步活动。
public interface CompletionStage<T>它创建了一个可能异步计算的阶段,该阶段在另一个 CompletionStage 完成时执行操作或计算值。

Java.util.concurrent 类

Class描述
public class CompletableFuture<T> extends Object implements Future<T>, CompletionStage<T>它是 Future,可以显式完成,并且可以用作 CompletionStage,支持在其完成时触发的依赖函数和操作。
public static class ConcurrentHashMap.KeySetView<K,V> extends Object implements Set<K>, Serializable它将 ConcurrentHashMap 视为一个键集,其中可以通过映射到公共值来选择性地启用添加。
public abstract class CountedCompleter<T> extends ForkJoinTask<T>一个 ForkJoinTask,在触发时执行完成操作,并且没有剩余的待处理操作。
public class CompletionException extends RuntimeException在完成结果或任务的过程中遇到错误或其他异常时,会抛出此异常。

java.util.concurrent.ConcurrentHashMap 类中的新方法

ConcurrentHashMap 类在其最新版本中引入了许多新方法。它包括各种 forEach 方法(forEach、forEachKey、forEachValue 和 forEachEntry)、搜索方法(search、searchKeys、searchValues 和 searchEntries)以及大量的归约方法(reduce、reduceToDouble、reduceToLong 等)。还添加了其他杂项方法(mappingCount 和 newKeySet)。

java.util.concurrent.atomic 中的新类

最新版本通过一小组新类 DoubleAccumulator、DoubleAdder、LongAccumulator 和 LongAdder 引入了可扩展、可更新的变量支持。它们在内部采用了减少争用的技术,与 Atomic 变量相比,吞吐量有了巨大提高。

Class描述
public class DoubleAccumulator extends Number implements Serializable用于一个或多个变量,这些变量共同维护一个使用提供的函数更新的运行双精度值。
public class DoubleAdder extends Number implements Serializable用于一个或多个变量,这些变量共同维护一个初始值为零的双精度总和。
public class LongAccumulator extends Number implements Serializable用于一个或多个变量,这些变量共同维护一个使用提供的函数更新的运行长整型值。
public class LongAdder extends Number implements Serializable用于一个或多个变量,这些变量共同维护一个初始值为零的长整型总和。

java.util.concurrent.ForkJoinPool 类中的新方法

此类添加了两个新方法 getCommonPoolParallelism() 和 commonPool(),它们分别返回公共池的目标并行度级别或公共池实例。

方法描述
public static ForkJoinPool commonPool()返回公共池实例。
Public static int getCommonPoolParallelism()返回公共池的目标并行度级别。

java.util.concurrent.locks.StampedLock 新类

添加了一个新类 StampedLock,用于添加基于功能的锁,具有三种模式用于控制读/写访问(写入、读取和乐观读取)。此类还支持提供跨三种模式的条件转换的方法。

Class描述
public class StampedLock extends Object implements Serializable此类表示一种基于功能的锁,具有三种模式用于控制读/写访问。

Java API for XML Processing (JAXP) 1.6 增强

在 Java 8 中,Java API for XML Processing (JAXP) 1.6 已添加。它要求使用 java.util.ServiceLoader 定义的服务提供者加载器机制来加载服务配置文件中的服务。

这样做的理由是允许 Java SE 平台进行未来的模块化,其中服务提供者可以通过除 JAR 文件以外的其他方式部署,并且可能无需服务配置文件。


Java 虚拟机增强

invokespecial 指令的验证已得到加强,因此只能调用当前类或其直接超类的实例初始化方法。


Java Mission Control 5.3 已包含在 Java 8 中

Java Mission Control (JMC) 是一套高级工具,可实现高效详细的数据分析,并提供高级、无干扰的 Java 监控和管理。JMC 提供了常见的分析领域的部分,例如代码性能、内存和延迟。

Java Mission Control 中默认包含日语和简体中文的 Babel 语言包,该语言包包含在 JDK 8 中。


Java 8 国际化增强

1) Unicode 增强

JDK 8 支持 Unicode 6.2.0。它包含以下功能:

  • 733 个新字符,包括土耳其里拉符号。
  • 7 种新文字:
    • Meroitic Hieroglyphs (麦罗埃象形文字)
    • Meroitic Cursive (麦罗埃草书)
    • Sora Sompeng (索拉·松彭)
    • Chakma (恰克马)
    • Sharada (沙拉达)
    • Takri (塔克里)
    • Miao (苗)
  • 11 个新区块:包括上述 7 种新文字的 7 个区块,以及以下现有文字的 4 个区块:
  • Arabic Extended-A (阿拉伯语扩展 A)
  • Sundanese Supplement (巽他语补充)
  • Meetei Mayek Extensions (梅泰梅伊扩展)
  • Arabic Mathematical Alphabetical Symbols (阿拉伯数学字母符号)

采用 Unicode CLDR 数据和 java.locale.providers 系统属性

Unicode 联盟发布了通用区域设置数据存储库 (CLDR) 项目,“以支持世界各地的语言,并提供最大、最全面的区域设置数据标准存储库。” CLDR 正在成为区域设置数据的实际标准。CLDR 的基于 XML 的区域设置数据已合并到 JDK 8 版本中,但默认情况下处于禁用状态。

有四种不同的区域设置数据源:

  • CLDR 代表 Unicode CLDR 项目提供的区域设置数据。
  • HOST 代表当前用户对底层操作系统设置的自定义。它仅与用户默认区域设置一起使用,并且可自定义的设置可能因操作系统而异,但主要支持日期、时间和数字、货币格式。
  • SPI 代表已安装 SPI 提供者中实现的区域设置敏感服务。
  • JRE 代表与先前 JRE 版本兼容的区域设置数据。

要选择所需的区域设置数据源,请使用 java.locale.providers 系统属性。按首选顺序列出数据源。例如:java.locale.providers=HOST,SPI,CLDR,JRE 默认行为等同于以下设置:java.locale.providers=JRE,SPI


Java 8 新日历和区域设置 API

JDK 8 包含两个新类、几个新方法以及一个现有静态方法的返回值。

java.util.spi 包中添加了两个新的抽象类用于服务提供者。

Class描述
public abstract class CalendarDataProvider extends LocaleServiceProvider这是一个抽象类,用于提供区域设置相关的 Calendar 参数的服务提供者。
public abstract class CalendarNameProvider extends LocaleServiceProvider这是一个抽象类,用于提供 Calendar 字段值的本地化字符串表示(显示名称)的服务提供者。

静态方法现在能够识别用于编号系统的 Locale.UNICODE_LOCALE_EXTENSION。

方法描述
public static final DecimalFormatSymbols getInstance(Locale locale)用于获取指定区域设置的 DecimalFormatSymbols 实例。此方法提供对 Java 运行时本身支持的区域设置以及已安装 DecimalFormatSymbolsProvider 实现所支持的区域设置的 DecimalFormatSymbols 实例的访问。如果 locale 为 null,则抛出 NullPointerException。

在 Calendar API 中添加了新方法

方法描述
public boolean isSupportedLocale(Locale locale)如果给定的区域设置受此区域设置服务提供者的支持,则返回 true。给定的区域设置可能包含应在确定支持时考虑的扩展。它定义在 java.util.spi.LocaleServiceProvider 类中。
public String getCalendarType()返回此 Calendar 的日历类型。日历类型由 Unicode Locale Data Markup Language (LDML) 规范定义。它定义在 java.util.Calendar 类中。

为 Calendar.getDisplayName 和 Calendar.getDisplayNames 方法添加了新的样式说明符,以确定 Calendar 名称的格式。


说明符描述
public static final int SHORT_FORMAT它是 getDisplayName 和 getDisplayNames 的样式说明符,表示用于格式化的短名称。
public static final int LONG_FORMAT它是 getDisplayName 和 getDisplayNames 的样式说明符,表示用于格式化的长名称。
public static final int SHORT_STANDALONE它是 getDisplayName 和 getDisplayNames 的样式说明符,表示独立使用的短名称,例如日历标题中的月份缩写。
public static final int LONG_STANDALONE它是 getDisplayName 和 getDisplayNames 的样式说明符,表示独立使用的长名称,例如日历标题中的月份名称。

两个新的 Locale 方法用于处理区域设置的(可选)扩展。

方法描述
public boolean hasExtensions()如果此 Locale 具有任何扩展,则返回 true。
public Locale stripExtensions()返回此 Locale 的副本,不带任何扩展。如果此 Locale 没有扩展,则返回该 Locale 本身。

两个新的 Locale.filter 方法根据 RFC 4647 中定义的标准返回符合条件的 Locale 实例列表。

方法描述
public static List<Locale> filter(List<Locale.LanguageRange> priorityList,Collection<Locale> locales)使用 RFC 4647 中定义的过滤机制,返回匹配的 Locale 实例列表。这等同于 filter(List, Collection, FilteringMode),当 mode 为 Locale.FilteringMode.AUTOSELECT_FILTERING 时。
public static List<Locale> filter(List<Locale.LanguageRange> priorityList,Collection<Locale> locales, Locale.FilteringMode mode)使用 RFC 4647 中定义的过滤机制,返回匹配的 Locale 实例列表。

两个新的 Locale.filterTags 方法根据 RFC 4647 中定义的标准返回匹配的语言标签列表。

方法描述
public static List<String> filterTags(List<Locale.LanguageRange> priorityList, Collection<String> tags)使用 RFC 4647 中定义的过滤机制,返回匹配的语言标签列表。这等同于 filterTags(List, Collection, FilteringMode),当 mode 为 Locale.FilteringMode.AUTOSELECT_FILTERING 时。
public static List<String> filterTags(List<Locale.LanguageRange> priorityList, Collection<String> tags, Locale.FilteringMode mode)使用 RFC 4647 中定义的过滤机制,返回匹配的语言标签列表。

两个新的 lookup 方法使用 RFC 4647 中定义的查找机制返回最佳匹配的区域设置或语言标签。

方法描述
public static Locale lookup(List<Locale.LanguageRange> priorityList, Collection<Locale> locales)使用 RFC 4647 中定义的查找机制,返回最佳匹配的语言标签的 Locale 实例。
Public static String lookupTag(List<Locale.LanguageRange> priorityList,Collection<String> tags)使用 RFC 4647 中定义的查找机制,返回最佳匹配的语言标签。

其他 Java 8 版本增强

JDK 8u5 增强

1) 应用程序的安全提示显示的频率已降低。


JDK 8u11 增强

1) 在 Java 控制面板的“高级”选项卡中,有一个选项可以抑制安装或更新 JRE 时来自赞助商的广告。

2) Entry-Point 属性可以包含在 JAR 文件清单中,以将一个或多个类标识为 RIA(富 Internet 应用程序)的有效入口点。


JDK 8u20 增强

1) javafxpackager 工具已重命名为 javapackager。此工具已通过用于自包含应用程序打包器的新参数得到增强。

以下增强与 java 工具相关:

  • 已添加一个与受限事务内存 (RTM) 相关的实验性 JIT 编译器选项。
  • 已添加几个与字符串去重相关的选项。
  • 已添加几个与高级加密标准 (AES) 内建函数相关的选项。
  • 已弃用几种垃圾回收选项的组合。

2) Java HotSpot 虚拟机已添加垃圾回收调优指南。它描述了 Java HotSpot VM 中包含的垃圾回收器,并帮助您决定哪个垃圾回收器可以最好地优化应用程序的性能,尤其是当它处理大量数据(数 GB)、拥有许多线程且事务速率很高时。


JDK 8u31 增强

1) 在此版本中,已从 Java 控制面板的高级选项中移除了 SSLv3 协议。


JDK 8u40 增强

Java 工具

1) 添加了 -XX:+CheckEndorsedAndExtDirs 选项,因为已弃用已发布标准覆盖机制 (JDK-8065675) 和扩展机制 (JDK-8065702)。该选项有助于识别这些机制的任何现有使用,并在 JDK 7u80 和 JDK 8u40 中得到支持。

2) Java Flight Recorder (JFR) 提供多种方式来解锁商业功能并为应用程序的运行时启用 JFR。

它包括 java 命令行选项,如 jcmd 诊断命令以及 Java Mission Control 中的图形用户界面 (GUI)控件。这种灵活性使您可以在启动时提供适当的选项,或稍后与 JFR 进行交互。

3) 选项 -XX:StartFlightRecording=parameter=value 有一个新参数 dumponexit={true|false},它指定是否在 JVM 以受控方式终止时生成 JFR 数据转储文件。

4) 与受限事务内存 (RTM) 相关的选项不再是实验性的。这些选项包括 -XX:RTMAbortRatio=abort_ratio、-XX:RTMRetryCount=number_of_retries、-XX:+UseRTMDeopt 和 -XX:+UseRTMLocking。

5) 在 Java 8 中,引入了应用程序类数据共享 (AppCDS)。AppCDS 扩展了 CDS(类数据共享),允许将标准扩展目录和应用程序类路径中的类放入共享归档中。这是一个商业功能,不再被认为是实验性的。

6) 添加了新选项 -XX:+ResourceManagement 和 -XX:ResourceManagementSampleInterval=value。

7) 增加了关于大页面的其他信息。大页面,也称为巨页,是比标准内存页面大小大得多的内存页面。大页面优化了处理器转换查找缓冲区。已记录 Linux 选项 -XX:+UseHugeTLBFS、-XX:+UseSHM 和 -XX:+UseTransparentHugePages。

8) 已记录选项 -XX:ObjectAlignmentInBytes=alignment。

JJS 工具

1) 添加了选项 --optimistic-types=[true|false]。它启用或禁用具有去优化重编译的乐观类型假设。

2) jjs 工具已添加选项 --language=[es5]。它指定 ECMAScript 语言版本。

Javapackager 工具

1) 为 OS X 打包器提供了新的参数。mac.CFBundleVersion 参数标识要使用的内部版本号。

2) mac.dmg.simple 参数指示是否跳过依赖执行 AppleScript 代码的 DMG 自定义步骤。

Jcmd 工具

Jcmd 工具用于动态地与 Java Flight Recorder (JFR) 进行交互。您可以使用它来解锁商业功能、启用/开始/停止飞行录制以及从系统中获取各种状态消息。

Jstat 工具

jstat 工具已更新,增加了关于压缩类空间的信息,这是元空间的一个特殊部分。

虚拟机

可伸缩原生内存跟踪 HotSpot VM 功能有助于诊断 VM 内存泄漏,并向用户澄清内存泄漏不在 VM 中的情况。原生内存跟踪器可以在大型系统上运行而无需自关闭,并且不会造成超出小型程序可接受范围的显著性能影响。

JDK 8 中引入了以下增强功能

  • JDK 中添加了一个新命令 jjs。此命令启动 Nashorn JavaScript 引擎,允许用户通过交互式 shell 或通过执行脚本文件来运行 JavaScript 代码。
  • 对 java 命令的增强现在使其能够启动 JavaFX 应用程序,前提是 JavaFX 应用程序已正确打包。有关类如何定位的指南可以在相关文档中找到。
  • 对 java 命令的手册页(提供 nroff 和 HTML 格式)进行了重大更新,将高级选项进行了全面重组,根据其影响区域分为运行时、编译器、垃圾收集和服务性等类别。此更新包括对几个以前未记录的选项的描述,以及一个专门介绍当前版本中已弃用或删除的选项的部分。
  • JDK 8 引入了 jdeps 命令行工具,旨在帮助开发人员分析类文件在包或类级别的依赖关系。
  • JDK 8 中已通过 Java Management Extensions (JMX) 启用了对诊断命令的远程访问,而这些命令以前只能通过 jcmd 工具在本地访问。现在可以通过 com.sun.management.DiagnosticCommandMBean 接口访问这些诊断命令,有关不同操作系统的 jcmd 工具文档中有更多详细信息。
  • jarsigner 工具已更新,添加了新的 -tsapolicyid 选项,允许用户向时间戳颁发机构 (TSA) 请求并附加时间戳到签名的 JAR 文件。
  • JDK 8 允许通过 java.lang.reflect.Executable.getParameters 方法检索任何方法或构造函数的正式参数名称。要启用此功能,.class 文件必须存储正式参数名称,这可以通过使用 javac 编译器的 -parameters 选项编译源文件来实现。
  • 从 JDK 8 开始,javac 编译器严格执行 Java 语言规范 (JLS) Section 15.21 的二元比较类型规则。这纠正了 javac 以前接受与 JLS 15.21 不符的某些 Object-primitive 比较的行为,现在将它们标记为类型错误。
  • JDK 8 中移除了 apt 工具及其在 com.sun.mirror 包中的相关 API。建议开发人员使用 javac 工具以及 javax.annotation.processing 和 javax.lang.model 包中的 API 进行注解处理。

Java 8 功能 MCQ

1. 在 Java 8 中使用 Lambda 表达式的主要优点是什么?

  1. 它们减少了异常处理的需要。
  2. 它们可以更轻松地创建线程。
  3. 它们支持函数式编程结构。
  4. 它们会自动处理内存管理。
 

答案:C

解释: Lambda 表达式有助于实现函数式接口,从而在 Java 中实现函数式编程范例。它们提供了一种简洁的方式来表示单方法接口(函数式接口)的实例,而无需创建匿名类。


2. 在 Java 8 中,使用哪个接口注解来指定函数式接口?

  1. @Functional
  2. @FunctionalInterface
  3. @SingleMethod
  4. @LambdaInterface
 

答案:B

解释: 在 Java 8 中,@FunctionalInterface 是一个可选注解,可以用来指示一个接口是函数式接口。它有助于防止开发人员意外地向接口添加多个抽象方法,这会使其函数式状态无效。


3. 使用 Java 8 中引入的 Stream API 有什么好处?

  1. 它允许直接访问硬件级资源。
  2. 它简化了图形用户界面 (GUI) 的使用。
  3. 它提供了一种声明式处理数据集合的方法。
  4. 它改进了内存分配技术。
 

答案:C

解释: Java 8 中的 Stream API 允许对元素流进行函数式风格的操作,例如过滤、映射和归约。它提供了一种声明式方法来处理数据集合,提高了代码的可读性和可维护性。


4. Java 8 的哪项功能允许接口具有方法实现?

  1. Lambda 表达式
  2. Stream API
  3. 默认方法
  4. 函数式接口
 

答案:C

解释: Java 8 中在接口中引入了默认方法,以允许接口提供方法实现。此功能通过允许接口在不破坏实现类的情况下进行演进,从而确保了向后兼容性。


5. 方法引用在 Java 8 中提供了什么?

  1. 调用静态方法的方式。
  2. 引用方法或构造函数的简洁语法。
  3. 定义函数的 Lambda 表达式的替代方法。
  4. 重载具有不同签名的参数的机制。
 

答案:B

解释: 方法引用是 Java 8 中的一项功能,它提供了一种不执行方法或构造函数即可引用它们的简写语法。当使用 Lambda 表达式调用方法时,它通过减少样板代码来提高代码的可读性。