当前位置: 首页 > java >正文

Java 11 新特性详解与代码示例

Java 11 新特性详解与代码示例

文章目录

  • Java 11 新特性详解与代码示例
    • 1. 新字符串方法
      • 1.1. `isBlank()`
      • 1.2. `lines()`
      • 1.3. `strip()`、`stripLeading()`、`stripTrailing()`
      • 1.4. `repeat(int n)`
    • 2. 新文件操作方法
      • 2.1. `Files.readString(Path path)`
      • 2.2. `Files.writeString(Path path, CharSequence csq)`
    • 3. Collection 的 `toArray` 方法
    • 4. `Predicate.not`
    • 5. Lambda 参数的局部变量语法
    • 6. HTTP 客户端 API
      • 6.1. 同步 GET 请求
      • 6.2. 异步 GET 请求
      • 6.3. POST 请求
    • 7. 直接运行 Java 文件
    • 8. 其他重要特性
    • 9. 结论
    • 10. 参考资料

Java 11(JDK 11)于 2018 年 9 月发布,是 Java 平台的长期支持(LTS)版本,带来了众多新特性和改进,涵盖了语言特性、标准库更新和 JVM 增强。本文将深入探讨 Java 11 的主要新特性,为每个特性提供详细的代码示例,并对优化现有功能的特性提供对比代码。我们的目标是提供“硬核”、深入的内容,确保读者能够理解每个特性的用途并在实际开发中应用。本文基于 Oracle 官方文档和其他可靠资源,确保信息准确。

在这里插入图片描述

1. 新字符串方法

Java 11 为 String 类引入了六个新方法,简化了常见的字符串操作任务。这些方法包括 isBlank()lines()strip()stripLeading()stripTrailing()repeat()。以下逐一介绍每个方法,并提供代码示例和与旧方法的对比。

1.1. isBlank()

isBlank() 方法检查字符串是否为空或仅包含空白字符(包括 Unicode 空白字符)。如果字符串为空或仅包含空白字符,返回 true;否则返回 false

public class IsBlankExample {public static void main(String[] args) {String str1 = "";String str2 = "   ";String str3 = "Hello";System.out.println("str1 is blank: " + str1.isBlank()); // trueSystem.out.println("str2 is blank: " + str2.isBlank()); // trueSystem.out.println("str3 is blank: " + str3.isBlank()); // false}
}

与旧方法的对比:在 Java 11 之前,开发者通常使用 str.trim().isEmpty() 来检查字符串是否为空或仅包含空白字符。然而,trim() 会创建一个新字符串,而 isBlank() 直接检查原始字符串,效率更高。

// Java 11 之前
String str = "   ";
boolean isBlank = str.trim().isEmpty(); // 创建新字符串,效率较低
System.out.println("str is blank: " + isBlank); // true

使用场景isBlank() 适用于表单验证、数据清理等场景,检查用户输入是否有效。

1.2. lines()

lines() 方法返回一个 Stream<String>,包含字符串中由换行符(\n\r\r\n)分隔的各行。这对于处理多行文本非常有用。

import java.util.stream.Stream;public class LinesExample {public static void main(String[] args) {String multiline = "Line 1\nLine 2\nLine 3";Stream<String> lines = multiline.lines();lines.forEach(System.out::println);// 输出:// Line 1// Line 2// Line 3}
}

与旧方法的对比:在 Java 11 之前,通常使用 split("\n") 来分割字符串,但这会一次性创建所有行的数组,对于大字符串可能消耗更多内存。lines() 返回流,支持延迟加载,效率更高。

// Java 11 之前
String multiline = "Line 1\nLine 2\nLine 3";
String[] lines = multiline.split("\n");
for (String line : lines) {System.out.println(line);
}

使用场景lines() 适合处理日志文件、CSV 文件或其他多行文本数据,结合流 API 可以高效地进行过滤或转换。

1.3. strip()stripLeading()stripTrailing()

这三个方法用于移除字符串中的空白字符。strip() 移除两端的空白字符,stripLeading() 移除开头的空白字符,stripTrailing() 移除末尾的空白字符。与 trim() 不同,这些方法能处理所有 Unicode 空白字符。

public class StripExample {public static void main(String[] args) {String str = "  Hello World  ";System.out.println("strip: '" + str.strip() + "'"); // "Hello World"System.out.println("stripLeading: '" + str.stripLeading() + "'"); // "Hello World  "System.out.println("stripTrailing: '" + str.stripTrailing() + "'"); // "  Hello World"// Unicode 空白字符String strWithUnicode = "\u2000Hello\u2000";System.out.println("trim: '" + strWithUnicode.trim() + "'"); // "\u2000Hello\u2000"System.out.println("strip: '" + strWithUnicode.strip() + "'"); // "Hello"}
}

与旧方法的对比trim() 仅移除 ASCII 控制字符和空格(代码点 <= \u0020),而 strip() 能移除所有 Unicode 空白字符(如 \u2000),功能更强大。

使用场景:这些方法适合处理国际化文本或需要精确控制空白字符的场景。

1.4. repeat(int n)

repeat(n) 方法返回一个新字符串,将原字符串重复 n 次。

public class RepeatExample {public static void main(String[] args) {String str = "Java";System.out.println(str.repeat(3)); // "JavaJavaJava"}
}

与旧方法的对比:在 Java 11 之前,重复字符串通常需要使用循环或 StringBuilder

// Java 11 之前
String str = "Java";
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 3; i++) {sb.append(str);
}
System.out.println(sb.toString()); // "JavaJavaJava"

使用场景repeat() 适合生成重复的文本模式,如格式化输出或测试数据生成。

2. 新文件操作方法

Java 11 为 java.nio.file.Files 类添加了 readStringwriteString 方法,简化了文件读写操作。

2.1. Files.readString(Path path)

readString 方法将文件内容直接读取为字符串。

import java.nio.file.Files;
import java.nio.file.Paths;
import java.io.IOException;public class ReadStringExample {public static void main(String[] args) {try {String content = Files.readString(Paths.get("file.txt"));System.out.println(content);} catch (IOException e) {e.printStackTrace();}}
}

与旧方法的对比:在 Java 11 之前,读取文件内容通常需要 Files.readAllBytesFiles.readAllLines

// Java 11 之前
try {String content = new String(Files.readAllBytes(Paths.get("file.txt")));System.out.println(content);
} catch (IOException e) {e.printStackTrace();
}// 或
try {List<String> lines = Files.readAllLines(Paths.get("file.txt"));String content = String.join("\n", lines);System.out.println(content);
} catch (IOException e) {e.printStackTrace();
}

使用场景readString 适合读取配置文件、JSON 文件等小型文本文件。

2.2. Files.writeString(Path path, CharSequence csq)

writeString 方法将字符串写入文件。

import java.nio.file.Files;
import java.nio.file.Paths;
import java.io.IOException;public class WriteStringExample {public static void main(String[] args) {try {Files.writeString(Paths.get("file.txt"), "Hello World");} catch (IOException e) {e.printStackTrace();}}
}

与旧方法的对比:在 Java 11 之前,写入字符串需要 Files.writeBufferedWriter

// Java 11 之前
try {Files.write(Paths.get("file.txt"), "Hello World".getBytes());
} catch (IOException e) {e.printStackTrace();
}// 或
try (BufferedWriter writer = Files.newBufferedWriter(Paths.get("file.txt"))) {writer.write("Hello World");
} catch (IOException e) {e.printStackTrace();
}

使用场景writeString 适合快速写入日志、配置文件等。

3. Collection 的 toArray 方法

Java 11 为 Collection 接口添加了新的默认方法 toArray(IntFunction<T[]> generator),允许指定如何创建数组,提高类型安全性和代码简洁性。

import java.util.Arrays;
import java.util.List;public class ToArrayExample {public static void main(String[] args) {List<String> list = Arrays.asList("a", "b", "c");String[] array = list.toArray(String[]::new);System.out.println(Arrays.toString(array)); // [a, b, c]}
}

与旧方法的对比:在 Java 11 之前,toArray 需要显式指定数组类型。

// Java 11 之前
List<String> list = Arrays.asList("a", "b", "c");
String[] array = list.toArray(new String[0]); // 或 new String[list.size()]
System.out.println(Arrays.toString(array)); // [a, b, c]

使用场景toArray(IntFunction) 适合需要将集合转换为特定类型数组的场景,如数据序列化或与遗留代码交互。

4. Predicate.not

Predicate 接口新增了静态方法 not,返回给定谓词的否定形式,提高流操作的可读性。

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;public class PredicateNotExample {public static void main(String[] args) {List<String> list = Arrays.asList("a", "", "b", " ");List<String> nonBlank = list.stream().filter(Predicate.not(String::isBlank)).collect(Collectors.toList());System.out.println(nonBlank); // [a, b]}
}

与旧方法的对比:在 Java 11 之前,需要使用 ! 运算符。

// Java 11 之前
List<String> list = Arrays.asList("a", "", "b", " ");
List<String> nonBlank = list.stream().filter(s -> !s.isBlank()).collect(Collectors.toList());
System.out.println(nonBlank); // [a, b]

使用场景Predicate.not 适合在流操作中需要否定谓词的场景,增强代码可读性。

5. Lambda 参数的局部变量语法

Java 11 允许在 Lambda 表达式参数中使用 var 关键字,支持添加注解而无需显式指定类型。

import java.util.function.BiFunction;
import javax.annotation.Nonnull;public class LambdaVarExample {public static void main(String[] args) {BiFunction<String, String, String> concat = (@Nonnull var s1, @Nonnull var s2) -> s1 + s2;System.out.println(concat.apply("Hello, ", "World!")); // Hello, World!}
}

与旧方法的对比:在 Java 11 之前,必须显式指定参数类型。

// Java 11 之前
BiFunction<String, String, String> concat = (@Nonnull String s1, @Nonnull String s2) -> s1 + s2;
System.out.println(concat.apply("Hello, ", "World!")); // Hello, World!

使用场景var 在 Lambda 参数中适合需要添加注解(如 @Nonnull)的场景,减少冗余代码。

6. HTTP 客户端 API

Java 11 引入了新的 HTTP 客户端 API(java.net.http 包),支持 HTTP/1.1 和 HTTP/2,以及异步请求,取代了旧的 HttpURLConnection

6.1. 同步 GET 请求

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.io.IOException;public class HttpClientGetExample {public static void main(String[] args) {try {HttpClient client = HttpClient.newHttpClient();HttpRequest request = HttpRequest.newBuilder().uri(URI.create("https://api.example.com/data")).build();HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());System.out.println("Status: " + response.statusCode());System.out.println("Body: " + response.body());} catch (IOException | InterruptedException e) {e.printStackTrace();}}
}

6.2. 异步 GET 请求

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;public class HttpClientAsyncExample {public static void main(String[] args) {HttpClient client = HttpClient.newHttpClient();HttpRequest request = HttpRequest.newBuilder().uri(URI.create("https://api.example.com/data")).build();client.sendAsync(request, HttpResponse.BodyHandlers.ofString()).thenApply(HttpResponse::body).thenAccept(System.out::println);}
}

6.3. POST 请求

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.io.IOException;public class HttpClientPostExample {public static void main(String[] args) {try {String json = "{\"key\":\"value\"}";HttpClient client = HttpClient.newHttpClient();HttpRequest request = HttpRequest.newBuilder().uri(URI.create("https://api.example.com/post")).header("Content-Type", "application/json").POST(HttpRequest.BodyPublishers.ofString(json)).build();HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());System.out.println("Status: " + response.statusCode());System.out.println("Body: " + response.body());} catch (IOException | InterruptedException e) {e.printStackTrace();}}
}

与旧方法的对比:在 Java 11 之前,使用 HttpURLConnection 进行 HTTP 请求。

import java.net.URL;
import java.net.HttpURLConnection;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;public class HttpUrlConnectionExample {public static void main(String[] args) {try {URL url = new URL("https://api.example.com/data");HttpURLConnection con = (HttpURLConnection) url.openConnection();con.setRequestMethod("GET");int status = con.getResponseCode();BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));String inputLine;StringBuilder content = new StringBuilder();while ((inputLine = in.readLine()) != null) {content.append(inputLine);}in.close();con.disconnect();System.out.println("Status: " + status);System.out.println("Body: " + content.toString());} catch (IOException e) {e.printStackTrace();}}
}

使用场景:新 HTTP 客户端 API 适合现代 Web 应用,支持 REST API 调用、WebSocket 等。

7. 直接运行 Java 文件

Java 11 允许使用 java 命令直接运行单文件 Java 源代码,无需先用 javac 编译。

public class HelloWorld {public static void main(String[] args) {System.out.println("Hello, World!");}
}

保存为 HelloWorld.java,然后运行:

java HelloWorld.java

输出

Hello, World!

与旧方法的对比:在 Java 11 之前,需要先编译再运行。

javac HelloWorld.java
java HelloWorld

使用场景:适合快速原型开发、脚本编写或教学。

8. 其他重要特性

以下是 Java 11 的其他值得注意的特性:

  • 嵌套访问控制(JEP 181):改进了 JVM 对嵌套类的访问控制,允许直接访问私有成员,无需桥接方法。
  • Epsilon 垃圾回收器(JEP 318):实验性无操作垃圾回收器,分配内存但不回收,适合性能测试。
  • Z 垃圾回收器(JEP 333):实验性低延迟垃圾回收器,适合大堆应用,暂停时间小于 10ms。
  • 飞行记录器(Flight Recorder):原为商业功能,现开源,提供低开销的性能分析。
  • 移除的模块:Java EE 和 CORBA 模块已从 JDK 移除,需单独引入依赖。
  • 废弃的模块:Nashorn JavaScript 引擎和 Pack200 压缩方案被标记为废弃。
  • Unicode 10 支持(JEP 327):支持 Unicode 10.0.0,新增字符和脚本。
  • TLS 1.3(JEP 332):支持最新的传输层安全协议,提升安全性和性能。
  • 新的加密算法(JEP 329):支持 ChaCha20 和 Poly1305 算法,替代旧的 RC4。

9. 结论

Java 11 作为 LTS 版本,为开发者提供了强大的工具和改进,从字符串和文件操作的简化到现代化的 HTTP 客户端 API,这些特性显著提高了代码质量和开发效率。通过本文的代码示例,开发者可以快速上手这些新功能,并在实际项目中应用。建议开发者尝试将这些特性融入现有项目,以充分利用 Java 11 的优势。

10. 参考资料

  • Oracle JDK 11 发行说明
  • Baeldung: Java 11 新特性
http://www.xdnf.cn/news/16609.html

相关文章:

  • Spring Boot中的this::语法糖详解
  • 递归推理树(RR-Tree)系统:构建认知推理的骨架结构
  • 力扣热题100--------240.搜索二维矩阵
  • Generative AI in Game Development
  • 板凳-------Mysql cookbook学习 (十二--------7)
  • 亚马逊 Vine 计划:评论生态重构与合规运营策略
  • C++基础:模拟实现queue和stack。底层:适配器
  • 解决mac下git pull、push需要输入密码
  • MySQL(配置)——MariaDB使用
  • 探索 Vim:Linux 下的高效文本编辑利器
  • SBB指令的“生活小剧场“
  • Linux 系统启动与 GRUB2 核心操作指南
  • Kafka运维实战 17 - kafka 分区副本从 1 增加到 3【实战】
  • 作物生长模型Oryza V3实战17:土壤数据集
  • 【RH134 问答题】第 9 章 访问网络附加存储
  • 2025年Solar应急响应公益月赛-7月笔记ing
  • 正运动控制器Zbasic回零详细教程(不带Z信号)
  • 【Linux知识】Linux Shell 脚本中的 `set -ex` 命令深度解析
  • SQL排查、分析海量数据以及锁机制
  • Fast Video generation with sliding tile attention
  • 2-verilog-基础语法
  • flask使用celery通过数据库定时
  • 【Linux我做主】探秘进程状态
  • Java中的有界队列和无界队列详解
  • CMake 目标文件后缀
  • react 项目怎么打断点
  • 大规模矩阵构建与高级算法应用
  • 【Linux篇】补充:消息队列和systemV信号量
  • 为什么分类任务偏爱交叉熵?MSE 为何折戟?
  • 【C++】判断语句