news 2026/7/14 20:20:09

JDK 9 新特性详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JDK 9 新特性详解

JDK 9 新特性详解

JDK 9(代号无官方名称,于2017年9月21日正式发布)是继 JDK 1.8 之后最重要的 Java 版本之一,也是 JDK 采用新的半年发布周期后的第一个 LTS 版本。它引入了模块化系统(Project Jigsaw)、JShell 交互式编程工具、集合工厂方法、Stream API 增强、全新的 HTTP Client API 等革命性特性,彻底改变了 Java 的生态架构和开发体验。


目录

  1. 模块化系统(Project Jigsaw / JPMS)
  2. JShell 交互式编程工具
  3. 集合工厂方法(Collection Factory Methods)
  4. 接口私有方法
  5. try-with-resources 增强
  6. Stream API 增强
  7. Optional 类增强
  8. HTTP Client API(全新)
  9. 钻石操作符增强(Diamond Operator)
  10. @SafeVarargs 扩展
  11. 进程 API 增强
  12. 多版本 JAR 文件(Multi-Release JAR)
  13. 统一 JVM 日志
  14. Compact Strings(紧凑字符串)
  15. VarHandle(变量句柄)
  16. 反应式流(Reactive Streams / Flow API)
  17. Stack-Walking API
  18. 其他重要特性
  19. JDK 9 特性总览表

1. 模块化系统(Project Jigsaw / JPMS)

1.1 概述

模块化系统是 JDK 9 最重要的特性,也是 Project Jigsaw 的核心成果。它将整个 JDK 拆分为约 70 个模块(java.basejava.sqljava.desktop等),同时允许开发者将自己的应用也组织为模块。

核心概念

概念说明
module-info.java模块描述文件,定义模块名称、依赖和导出
requires声明对其他模块的依赖
exports声明对外暴露的包
opens声明允许反射访问的包
uses声明使用的服务接口
provides声明提供的服务实现
transitive传递依赖(依赖的依赖也对外可见)

模块图示例

module com.example.app { requires java.sql; // 依赖 java.sql 模块 requires transitive java.logging; // 传递依赖 exports com.example.app.api; // 对外暴露 api 包 opens com.example.app.model to javax.persistence; // 允许反射 uses com.example.app.spi.Plugin; // 使用服务 provides com.example.app.spi.Plugin with com.example.app.impl.MyPlugin; }

目录结构

src/ ├── module-info.java // 模块描述 └── com/ └── example/ └── app/ ├── api/ │ └── UserService.java // 对外暴露 └── internal/ └── UserDao.java // 不暴露,外部不可访问

模块化的好处

  • 封装性:未exports的包对外不可见(强封装)
  • 可靠性:明确声明依赖关系,避免类路径冲突(JAR Hell)
  • 可维护性:模块边界清晰,便于理解和维护
  • 可扩展性:支持服务发现和加载(uses/provides
  • 可裁剪性:自定义 JRE 只包含需要的模块(jlink工具)

1.2 代码案例

// ============ 模块描述文件示例 ============// ---- 模块 A:com.example.service ----// 文件路径:src/com.example.service/module-info.javamodulecom.example.service{requiresjava.sql;// 依赖 JDBCrequirestransitivejava.logging;// 传递依赖(使用方也能用日志)exportscom.example.service.api;// 只暴露 api 包exportscom.example.service.model;// 暴露 model 包}// ---- 模块 B:com.example.app ----// 文件路径:src/com.example.app/module-info.javamodulecom.example.app{requirescom.example.service;// 依赖模块 Arequiresjava.logging;// 直接使用日志}// ---- 模块 C:服务提供者 ----// 文件路径:src/com.example.service.impl/module-info.javamodulecom.example.service.impl{requirescom.example.service;providescom.example.service.api.UserServicewithcom.example.service.impl.UserServiceImpl;}// ============ 使用 jlink 创建自定义 JRE ============// 命令:只包含需要的模块// jlink --module-path mods --add-modules com.example.app \// --output custom-jre --strip-debug --compress 2// ============ 编译和运行模块 ============// 编译模块:// javac -d mods/com.example.service src/com.example.service/module-info.java src/com.example.service/com/example/service/api/*.java// 运行模块:// java --module-path mods --module com.example.app/com.example.app.Main

2. JShell 交互式编程工具

2.1 概述

JShell 是 JDK 9 引入的REPL(Read-Eval-Print-Loop)工具,允许在命令行中交互式地编写和执行 Java 代码片段,无需创建完整的类和main方法。

核心特点

  • 即时执行代码片段(表达式、语句、方法、类)
  • 自动补全(Tab 键)
  • 前向引用(先使用方法再定义)
  • 保留历史记录(/history
  • 支持自定义脚本(/open
  • 错误反馈即时可见

常用命令

命令说明
/help帮助信息
/list列出所有代码片段
/edit打开编辑器
/save <file>保存到文件
/open <file>加载文件
/exit退出
/reset重置状态
/vars列出所有变量
/methods列出所有方法
/types列出所有类型
/imports列出所有导入
/history历史记录
/drop <id>删除指定片段

2.2 代码案例

// ============ 启动 JShell ============// 命令行输入:jshell// ============ 基本使用 ============// 直接计算表达式jshell>2+3$1==>5// 声明变量jshell>Stringname="JDK 9"name==>"JDK 9"// 使用变量jshell>System.out.println("Hello "+name)HelloJDK9// 定义方法(无需类包装)jshell>intfactorial(intn){...>returnn<=1?1:n*factorial(n-1);...>}|created methodfactorial(int)// 调用方法jshell>factorial(5)$5==>120// 前向引用(先调用后定义)jshell>System.out.println(greet("World"))Hello,World!jshell>Stringgreet(Stringname){...>return"Hello, "+name+"!";...>}|created methodgreet(String)|已更新方法greet(String)的引用// ============ 导入包 ============jshell>importjava.time.*jshell>LocalDate.now()$8==>2024-01-15// ============ 查看历史 ============jshell>/list1:2+32:Stringname="JDK 9"3:System.out.println("Hello "+name)4:intfactorial(intn){returnn<=1?1:n*factorial(n-1);}5:factorial(5)// ============ 保存和加载脚本 ============jshell>/save myscript.jsh jshell>/openmyscript.jsh// ============ 退出 ============jshell>/exit|再见// ============ 命令行参数 ============// jshell --class-path libs/* 指定类路径// jshell --startup myinit.jsh 指定启动脚本// jshell -v 详细模式// jshell -q 安静模式

3. 集合工厂方法(Collection Factory Methods)

3.1 概述

JDK 9 为集合接口引入了of()ofEntries()工厂方法,可以简洁地创建不可变集合(Immutable Collections)。这是对 JDK 1.8 中Collections.unmodifiableList()和 GuavaImmutableList.of()的标准化替代。

核心特点

  • 返回不可变集合(add/removeUnsupportedOperationException
  • 不允许null元素(立即抛NullPointerException
  • 内存高效(内部使用紧凑数据结构)
  • 支持 0~10 个参数的重载 + 可变参数重载
  • 序列化支持

支持的方法

接口方法
ListList.of(),List.of(e1, e2, ...),List.of(E[])
SetSet.of(),Set.of(e1, e2, ...),Set.of(E[])
MapMap.of(),Map.of(k1,v1, k2,v2, ...),Map.ofEntries(Map.Entry...)
Map.EntryMap.entry(K key, V value)

3.2 代码案例

// ============ 1. List.of() 创建不可变列表 ============// JDK 8 写法List<String>oldList=Collections.unmodifiableList(Arrays.asList("a","b","c"));// JDK 9 写法List<String>list1=List.of("a","b","c");List<String>list2=List.of();// 空列表List<String>list3=List.of("single");// 单元素// 不可变性验证try{list1.add("d");// 抛出 UnsupportedOperationException}catch(UnsupportedOperationExceptione){System.out.println("不可变集合,无法修改");}// 不允许 nulltry{List<String>nullList=List.of("a",null,"c");// 抛出 NullPointerException}catch(NullPointerExceptione){System.out.println("不允许 null 元素");}// ============ 2. Set.of() 创建不可变集合 ============Set<String>set1=Set.of("a","b","c");Set<Integer>set2=Set.of(1,2,3,4,5);Set<String>emptySet=Set.of();// 自动去重(注意:重复元素会抛异常,不同于 Set 构造器)try{Set<String>dupSet=Set.of("a","a","b");// 抛出 IllegalArgumentException}catch(IllegalArgumentExceptione){System.out.println("Set.of() 不允许重复元素");}// ============ 3. Map.of() 创建不可变映射 ============// 最多 10 个键值对的重载Map<String,Integer>map1=Map.of("one",1,"two",2,"three",3);// 空 MapMap<String,String>emptyMap=Map.of();// ============ 4. Map.ofEntries() 超过 10 个键值对 ============Map<String,Integer>bigMap=Map.ofEntries(Map.entry("a",1),Map.entry("b",2),Map.entry("c",3),Map.entry("d",4),Map.entry("e",5),Map.entry("f",6),Map.entry("g",7),Map.entry("h",8),Map.entry("i",9),Map.entry("j",10),Map.entry("k",11)// 超过 10 个必须用 ofEntries);// ============ 5. 实际应用场景 ============// 常量集合publicclassConstants{publicstaticfinalList<String>SUPPORTED_FORMATS=List.of("json","xml","yaml","csv");publicstaticfinalSet<String>RESERVED_KEYWORDS=Set.of("if","else","for","while","return","class");publicstaticfinalMap<String,String>MIME_TYPES=Map.of("json","application/json","xml","application/xml","html","text/html","txt","text/plain");}// 方法参数快速构建publicvoidprocessConfig(){Map<String,Object>config=Map.of("host","localhost","port",8080,"timeout",3000);// 传递给处理方法}// Stream 中快速构建List<String>result=List.of("a","b","c").stream().map(String::toUpperCase).collect(Collectors.toList());// ============ 6. 与 JDK 8 写法对比 ============// JDK 8List<String>jdk8List=Collections.unmodifiableList(newArrayList<>(Arrays.asList("a","b","c")));// JDK 9List<String>jdk9List=List.of("a","b","c");// JDK 8Map<String,Integer>jdk8Map=newHashMap<>();jdk8Map.put("a",1);jdk8Map.put("b",2);Map<String,Integer>unmodifiableMap=Collections.unmodifiableMap(jdk8Map);// JDK 9Map<String,Integer>jdk9Map=Map.of("a",1,"b",2);

4. 接口私有方法

4.1 概述

JDK 9 允许在接口中定义private方法(包括private static方法),用于复用default方法和static方法中的公共逻辑,避免代码重复。

规则

  • private方法只能在接口内部被defaultstatic方法调用
  • 不能被实现类访问
  • private static方法可被其他static方法和default方法调用
  • private非静态方法只能被default方法调用

4.2 代码案例

// ============ 1. 接口私有方法 ============publicinterfaceLogger{// 默认方法defaultvoidlogInfo(Stringmessage){log("INFO",message);// 调用私有方法}defaultvoidlogError(Stringmessage){log("ERROR",message);// 调用私有方法}defaultvoidlogDebug(Stringmessage){log("DEBUG",message);// 调用私有方法}// 私有方法:复用日志格式化逻辑privatevoidlog(Stringlevel,Stringmessage){Stringtimestamp=java.time.LocalDateTime.now().toString();System.out.println("["+timestamp+"] ["+level+"] "+message);}}// ============ 2. 接口私有静态方法 ============publicinterfaceValidator<T>{defaultbooleanvalidate(Tvalue){returncheckNotNull(value)&&checkValid(value);}static<T>Validator<T>of(java.util.function.Predicate<T>predicate){returnvalue->checkNotNull(value)&&predicate.test(value);}// 私有静态方法:复用非空检查privatestatic<T>booleancheckNotNull(Tvalue){if(value==null){thrownewIllegalArgumentException("Value must not be null");}returntrue;}// 抽象方法booleancheckValid(Tvalue);}// ============ 3. 实际应用:数据转换器接口 ============publicinterfaceDataConverter<S,T>{defaultTconvert(Ssource){if(isNull(source)){returngetDefault();}returndoConvert(source);}defaultList<T>convertAll(List<S>sources){if(isNull(sources)||sources.isEmpty()){returnList.of();}returnsources.stream().filter(s->!isNull(s)).map(this::doConvert).collect(Collectors.toList());}TdoConvert(Ssource)
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/14 20:19:24

Veritas NetBackup 10.1 Windows管理控制台部署与安全访问配置

1. Veritas NetBackup管理控制台基础认知作为企业级备份解决方案的核心组件&#xff0c;Veritas NetBackup管理控制台是管理员日常运维的"作战指挥中心"。这个基于Java的图形化界面可以同时管理Windows和UNIX环境下的主服务器、介质服务器及客户端&#xff0c;就像用…

作者头像 李华
网站建设 2026/7/14 20:17:15

Python计算机视觉入门:从环境搭建到数字识别项目实战

如果你刚接触计算机视觉&#xff0c;可能会被各种复杂的算法和数学公式吓退。但实际情况是&#xff0c;现代Python生态已经让计算机视觉的门槛大幅降低——你不需要成为数学博士&#xff0c;也能快速构建实用的视觉应用。 这篇文章要解决的核心问题是&#xff1a; 零基础开发…

作者头像 李华
网站建设 2026/7/14 20:12:51

多维聚合的本质:操作域与定义域的错位解析

1. 这不是简单的“groupby加sum”——多维聚合中的数据变形本质你有没有遇到过这样的场景&#xff1a;一张销售明细表&#xff0c;字段包括地区、产品线、季度、客户等级、销售额、成本、订单数&#xff1b;老板突然甩来一句&#xff1a;“按地区产品线季度三个维度&#xff0c…

作者头像 李华
网站建设 2026/7/14 20:11:46

湿法冶炼XRF-ICP-EDS交叉验证与DCS-LIMS集成项目方案

依托DCS生产数据LIMS检化验结果&#xff0c;实现XRF、ICP、EDS三类设备数据的行业标准交叉验证&#xff0c;可按以下全流程落地&#xff1a;一、前置基础配置‌设备数据打通适配‌完成XRF、ICP、EDS与LIMS的接口对接&#xff0c;适配不同厂商的私有数据格式&#xff0c;保障数据…

作者头像 李华