JDK 9 其他特性
除了模块系统,JDK 9 还带来了一系列实用改进。这一节聊聊那些不太起眼但很有用的新功能。
String 新方法
String 类新增了 5 个实用方法:
java
public class StringNewMethodsDemo {
public static void main(String[] args) {
// isBlank() - 判断是否空白(JDK 11+)
System.out.println("".isBlank()); // true
System.out.println(" ".isBlank()); // true(空格)
System.out.println("\t\n".isBlank()); // true(Tab/换行)
System.out.println("hello".isBlank()); // false
// lines() - 按行分割(JDK 11+)
String multiline = "line1\nline2\nline3";
multiline.lines().forEach(System.out::println);
// 输出:
// line1
// line2
// line3
// strip() vs trim() - 去空白
String withSpace = " hello ";
System.out.println("strip: '" + withSpace.strip() + "'"); // 'hello'
System.out.println("trim: '" + withSpace.trim() + "'"); // 'hello'
// 区别:strip 处理 Unicode 空白,trim 只处理 ASCII
// stripLeading() / stripTrailing()
System.out.println("'" + " hello ".stripLeading() + "'"); // 'hello '
System.out.println("'" + " hello ".stripTrailing() + "'"); // ' hello'
// repeat() - 重复字符串(JDK 11+)
System.out.println("na ".repeat(3) + "Batman!");
// "na na na Batman!"
}
}| 方法 | JDK 版本 | 说明 |
|---|---|---|
isBlank() | 11 | 是否为空白(空格、Tab、换行等) |
lines() | 11 | 按行分割,返回 Stream<String> |
strip() | 11 | 去除前后空白(Unicode) |
stripLeading() | 11 | 只去除前导空白 |
stripTrailing() | 11 | 只去除尾部空白 |
repeat() | 11 | 重复字符串 N 次 |
注意:这些方法实际上是在 JDK 11 才加入的,但因为是 JDK 9 模块化带来的 String 改进相关,放在一起讲。
Stream 增强
JDK 9 为 Stream 添加了 3 个新方法:
java
import java.util.stream.*;
public class StreamEnhancementsDemo {
public static void main(String[] args) {
// takeWhile - 取元素直到条件不满足
System.out.println("=== takeWhile ===");
Stream.of(1, 2, 3, 4, 1, 2)
.takeWhile(n -> n < 3)
.forEach(System.out::println);
// 输出:1, 2(遇到 4 不满足就停了,不再处理后面的 1, 2)
// dropWhile - 跳过元素直到条件不满足
System.out.println("=== dropWhile ===");
Stream.of(1, 2, 3, 4, 1, 2)
.dropWhile(n -> n < 3)
.forEach(System.out::println);
// 输出:3, 4, 1, 2(跳过 1, 2,遇到 3 开始保留)
// ofNullable - 从可空值创建 Stream
System.out.println("=== ofNullable ===");
String nullable = null;
long count1 = Stream.ofNullable(nullable).count(); // 0
String value = "hello";
long count2 = Stream.ofNullable(value).count(); // 1
// 实际场景
Optional<String> opt = Optional.ofNullable(getConfig());
opt.stream().forEach(System.out::println);
}
private static String getConfig() {
return null;
}
}Optional 增强
JDK 9 为 Optional 添加了 3 个实用方法:
java
import java.util.Optional;
public class OptionalEnhancementsDemo {
public static void main(String[] args) {
Optional<String> empty = Optional.empty();
Optional<String> present = Optional.of("hello");
// or() - 如果为空,提供另一个 Optional(JDK 9+)
System.out.println("=== or ===");
Optional<String> result1 = empty.or(() -> Optional.of("default"));
System.out.println(result1.orElse("nothing")); // "default"
Optional<String> result2 = present.or(() -> Optional.of("default"));
System.out.println(result2.orElse("nothing")); // "hello"
// ifPresentOrElse - 有值执行第一个,无值执行第二个(JDK 9+)
System.out.println("=== ifPresentOrElse ===");
present.ifPresentOrElse(
v -> System.out.println("有值: " + v),
() -> System.out.println("无值")
);
// 输出:有值: hello
empty.ifPresentOrElse(
v -> System.out.println("有值: " + v),
() -> System.out.println("无值")
);
// 输出:无值
// stream() - 转成 Stream(JDK 9+)
System.out.println("=== stream ===");
long count1 = empty.stream().count(); // 0
long count2 = present.stream().count(); // 1
// 实用场景:处理可能为空的值
Optional<String> config = getConfig();
List<String> configs = config.stream()
.flatMap(c -> parseConfig(c).stream())
.toList();
}
private static Optional<String> getConfig() {
return Optional.empty();
}
private static List<String> parseConfig(String config) {
return List.of();
}
}Process API
JDK 9 之前,获取进程信息需要调用本地方法。JDK 9 提供了 ProcessHandle:
java
import java.time.Duration;
import java.time.Instant;
public class ProcessApiDemo {
public static void main(String[] args) {
// 获取当前进程
ProcessHandle current = ProcessHandle.current();
System.out.println("当前进程 PID: " + current.pid());
// 进程信息
ProcessHandle.Info info = current.info();
System.out.println("进程命令: " + info.command().orElse("unknown"));
System.out.println("启动参数: " + info.arguments().orElse(new String[0]));
System.out.println("启动时间: " + info.startInstant().orElse(Instant.now()));
System.out.println("CPU 耗时: " + info.totalCpuDuration().orElse(Duration.ZERO));
// 获取父进程
ProcessHandle parent = current.parent();
System.out.println("父进程 PID: " + parent.map(ProcessHandle::pid).orElse(-1L));
// 列出所有进程
System.out.println("\n=== 所有进程 ===");
ProcessHandle.allProcesses()
.limit(5)
.forEach(p -> {
String name = p.info().command().orElse("unknown");
System.out.println("PID " + p.pid() + ": " + name);
});
// 销毁进程
// current.destroy(); // 请求终止
// current.destroyForcibly(); // 强制终止
}
}集合的 toArray() 增强
JDK 11 增强了集合的 toArray() 方法:
java
import java.util.*;
public class ToArrayEnhancementDemo {
public static void main(String[] args) {
List<String> list = List.of("a", "b", "c");
// 以前的方式
String[] arr1 = list.toArray(new String[0]);
// JDK 11+:更简洁
String[] arr2 = list.toArray(String[]::new);
// toArray(IntFunction<T[]> generator) - 接收泛型数组构造器
System.out.println(Arrays.toString(arr2)); // [a, b, c]
}
}反应式流(Flow API)
JDK 9 引入了 java.util.concurrent.Flow API,作为反应式流的标准接口:
java
import java.util.concurrent.Flow.*;
public class FlowApiDemo {
public static void main(String[] args) {
// 发布者
SubmissionPublisher<String> publisher = new SubmissionPublisher<>();
// 订阅者
Flow.Subscription subscription = null;
publisher.subscribe(new Flow.Subscriber<String>() {
@Override
public void onSubscribe(Flow.Subscription s) {
this.subscription = s;
s.request(1); // 请求一个元素
}
@Override
public void onNext(String item) {
System.out.println("收到: " + item);
subscription.request(1); // 处理完再请求下一个
}
@Override
public void onError(Throwable t) {
t.printStackTrace();
}
@Override
public void onComplete() {
System.out.println("完成");
}
});
// 发布数据
publisher.submit("消息1");
publisher.submit("消息2");
publisher.submit("消息3");
publisher.close();
// 等待处理完成
try { Thread.sleep(100); } catch (Exception e) {}
}
}小结
JDK 9 的改进虽然不如模块系统那么重磅,但都很实用:
| 特性 | 用途 |
|---|---|
| String 新方法 | 更方便的字符串处理 |
| Stream 增强 | takeWhile、dropWhile、ofNullable |
| Optional 增强 | or、ifPresentOrElse、stream |
| Process API | 获取和管理进程信息 |
| Flow API | 反应式流标准接口 |
| 集合工厂 | List.of、Set.of、Map.of |
这些改进共同的目标是:减少样板代码,让常见操作更简洁。
