Skip to content

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 增强takeWhiledropWhileofNullable
Optional 增强orifPresentOrElsestream
Process API获取和管理进程信息
Flow API反应式流标准接口
集合工厂List.ofSet.ofMap.of

这些改进共同的目标是:减少样板代码,让常见操作更简洁

基于 VitePress 构建