前言
Java 11 于 2018 年 9 月发布,是继 Java 8 之后的又一个长期支持版本(LTS)。
1. 字符串增强
Java 11 为 String
类增加了多个实用方法,大大简化了字符串处理。
1.1 strip() 系列方法
相比 trim()
,新的 strip()
方法可以处理 Unicode 空白字符。
arduino
// 移除字符串首尾的空白符
String text = " Hello Java 11! ";
System.out.println("使用trim(): [" + text.trim() + "]"); // [Hello Java 11!]
System.out.println("使用strip(): [" + text.strip() + "]"); // [Hello Java 11!]
// 仅移除开头的空白符
System.out.println("使用stripLeading(): [" + text.stripLeading() + "]"); // [Hello Java 11! ]
// 仅移除结尾的空白符
System.out.println("使用stripTrailing(): [" + text.stripTrailing() + "]"); // [ Hello Java 11!]
对于包含 Unicode 空白字符的情况,strip()
的优势更加明显:
csharp
String textWithUnicode = "\u2005Hello Java 11!\u2005";
System.out.println("使用trim(): [" + textWithUnicode.trim() + "]"); // 不能正确处理 Unicode 空白
System.out.println("使用strip(): [" + textWithUnicode.strip() + "]"); // 正确处理 Unicode 空白
1.2 isBlank() 方法
判断字符串是否为空或仅包含空白字符:
ini
String empty = "";
String blank = " \t \n ";
String notBlank = "Java";
System.out.println(empty.isBlank()); // true
System.out.println(blank.isBlank()); // true
System.out.println(notBlank.isBlank()); // false
1.3 lines() 方法
将字符串按行分割并返回流:
arduino
String multiLine = "Java\n11\nFeatures";
multiLine.lines().forEach(System.out::println);
// 输出:
// Java
// 11
// Features
// 结合其他 Stream 操作使用
long lineCount = multiLine.lines().count();
System.out.println("行数: " + lineCount); // 3
1.4 repeat() 方法
将字符串重复指定次数:
arduino
String str = "Java";
System.out.println(str.repeat(3)); // JavaJavaJava
// 创建分隔线
String dash = "-";
System.out.println(dash.repeat(50)); // 输出 50 个连字符
// 创建缩进
String createIndent(int level) {
return " ".repeat(level * 2);
}
System.out.println(createIndent(2) + "Hello"); // " Hello"
2. 集合增强
2.1 Collection.toArray(IntFunction)
新的 toArray
方法允许更简洁地将集合转换为指定类型的数组:
ini
List<String> list = List.of("Java", "11", "Features");
// Java 8 方式
String[] array1 = list.toArray(new String[0]);
// Java 11 方式 - 使用数组构造器引用
String[] array2 = list.toArray(String[]::new);
// 使用其他类型
Integer[] numbers = List.of(1, 2, 3).toArray(Integer[]::new);
3. Lambda 参数的局部变量语法
Java 11 允许在 Lambda 表达式的参数中使用 var
关键字,增强代码的一致性并允许添加注解:
less
// 不使用 var
Consumer<String> consumer1 = (String s) -> System.out.println(s);
// 使用 var
Consumer<String> consumer2 = (var s) -> System.out.println(s);
// var 的主要优势:可以添加注解
import java.util.Objects;
Consumer<String> consumer3 = (@NotNull var s) -> System.out.println(s);
// 多参数示例
BiFunction<String, String, Integer> comparator =
(@NotNull var s1, @NotNull var s2) -> s1.compareTo(s2);
4. 标准 HTTP 客户端 API
Java 11 将 HTTP 客户端 API标准化,并放在 java.net.http
包中。
4.1 基本用法
arduino
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
// 创建客户端
HttpClient client = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_2) // 默认使用 HTTP/2
.connectTimeout(Duration.ofSeconds(10))
.build();
// 创建请求
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.github.com/users/octocat"))
.header("Accept", "application/json")
.GET() // GET 是默认方法,可以省略
.build();
// 发送同步请求
HttpResponse<String> response = client.send(
request,
HttpResponse.BodyHandlers.ofString()
);
// 处理响应
System.out.println("状态码: " + response.statusCode());
System.out.println("响应体: " + response.body());
4.2 异步请求
scss
// 使用相同的 client 和 request
// 发送异步请求
client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.thenAccept(System.out::println)
.join(); // 等待完成
4.3 POST 请求
less
// 创建 POST 请求
HttpRequest postRequest = HttpRequest.newBuilder()
.uri(URI.create("https://postman-echo.com/post"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString("{"name":"Java 11"}"))
.build();
// 发送请求
HttpResponse<String> postResponse = client.send(
postRequest,
HttpResponse.BodyHandlers.ofString()
);
System.out.println("POST 响应: " + postResponse.body());
4.4 处理不同类型的响应体
ini
// 获取字节数组响应
HttpResponse<byte[]> binaryResponse = client.send(
request,
HttpResponse.BodyHandlers.ofByteArray()
);
// 获取输入流
HttpResponse<InputStream> streamResponse = client.send(
request,
HttpResponse.BodyHandlers.ofInputStream()
);
// 直接将响应保存到文件
HttpResponse<Path> fileResponse = client.send(
request,
HttpResponse.BodyHandlers.ofFile(Paths.get("response.json"))
);
4.5 配置 WebSocket
typescript
// WebSocket 客户端
HttpClient webSocketClient = HttpClient.newHttpClient();
WebSocket webSocket = webSocketClient.newWebSocketBuilder()
.buildAsync(URI.create("wss://echo.websocket.org"), new WebSocket.Listener() {
@Override
public void onOpen(WebSocket webSocket) {
System.out.println("WebSocket 连接已打开");
webSocket.request(1);
}
@Override
public CompletionStage<?> onText(WebSocket webSocket,
CharSequence message,
boolean last) {
System.out.println("接收到消息: " + message);
webSocket.request(1);
return CompletableFuture.completedFuture(null);
}
@Override
public CompletionStage<?> onClose(WebSocket webSocket,
int statusCode,
String reason) {
System.out.println("WebSocket 已关闭: " + reason);
return CompletableFuture.completedFuture(null);
}
}).join();
// 发送消息
webSocket.sendText("Hello, WebSocket!", true);
5. 单文件源代码程序
Java 11 允许直接运行单个源代码文件,无需先编译为 class 文件。这对于简单脚本和原型开发非常有用。
5.1 基本用法
创建 HelloJava11.java
文件:
csharp
// 无需 public class 声明
// 文件名可以与类名不匹配
void main() {
System.out.println("Hello Java 11!");
// 直接使用 Java 11 的新特性
var text = " Java 11 ";
System.out.println(text.strip());
}
直接运行:
java HelloJava11.java
6. 其他 API 改进
6.1 Optional 增强
arduino
import java.util.Optional;
// 当值不存在时执行操作
Optional<String> optional = Optional.empty();
optional.ifPresentOrElse(
value -> System.out.println("值: " + value),
() -> System.out.println("值不存在")
); // 输出: 值不存在
// 如果为空则返回备选的 Optional
Optional<String> result = optional.or(() -> Optional.of("默认值"));
System.out.println(result.get()); // 输出: 默认值
// 转换为 Stream
Optional<String> optional2 = Optional.of("Java");
optional2.stream().forEach(System.out::println); // 输出: Java
6.2 Files 类新方法
arduino
import java.nio.file.Files;
import java.nio.file.Path;
// 读取文件内容为字符串
String content = Files.readString(Path.of("file.txt"));
// 写入字符串到文件
Files.writeString(Path.of("output.txt"), "Hello Java 11");
// 判断两个文件是否相同
boolean isSame = Files.mismatch(Path.of("file1.txt"), Path.of("file2.txt")) == -1;
6.3 Path 改进
ini
import java.nio.file.Path;
// 转换 String 为 Path 的简化方法
Path path = Path.of("/home", "user", "docs");
Path path2 = Path.of(URI.create("file:///home/user/docs"));
6.4 Predicate 接口新方法
ini
import java.util.function.Predicate;
import java.util.List;
List<String> list = List.of("Java", "", "11", null, "Features");
// 返回不满足原始条件的 Predicate
Predicate<String> isNotBlank = Predicate.not(String::isBlank);
// 过滤非空且非空白的字符串
list.stream()
.filter(Objects::nonNull)
.filter(isNotBlank)
.forEach(System.out::println);
7. 总结
Java 11 作为长期支持版本,提供了大量实用的新特性和改进,包括字符串处理增强、标准 HTTP 客户端、单文件源代码执行等,同时在性能、安全性和开发体验方面也有显著提升。
作为 Java 开发人员,熟练掌握这些新特性将帮助我们编写更简洁、高效的代码,并提高开发效率。特别是标准 HTTP 客户端和字符串处理方法,为我们处理常见任务提供了更强大的工具。