JDK 8 把写法范式定下来了JDK 9 干的是另一件大事——给 JDK 自身和你的应用做模块化。这是 Java 历史上改动最底层的一次发布连 JDK 内部都拆成了几十个模块也带来了程序员能直接玩的两个甜点JShell 和一堆语法糖。这一篇讲清楚三件事模块化JPMS到底改了什么、为什么它叫好不叫座、以及 JShell 和那些小特性怎么帮你提效。一、JPMSJava 平台模块系统JDK 9 之前所有类都在一个巨大的 classpath 上自由恋爱——任何代码能new任何类连 JDK 内部的sun.misc.Unsafe都被各种框架偷偷调用JDK 团队想改内部 API 寸步难行。模块化就是要把这种混乱收口。模块用module-info.java声明modulecom.example.app{requiresjava.sql;// 依赖哪个模块requirestransitivecom.example.lib;// 传递依赖exportscom.example.app.api;// 只暴露这个包别的包外部看不到openscom.example.app.dto;// 反射开放序列化/框架用}核心规则强封装没exports的包外部代码编译期都碰不到连反射默认也不行需opens。可靠配置启动时就检查依赖是否齐全而不是运行时才ClassNotFoundException。可见性收敛requires必须显式声明不再有隐式万能 classpath。理想很丰满强封装能让 JDK 放心删掉/改写内部 API应用边界也更清晰。但现实骨感——二、为什么模块化叫好不叫座迁移成本太高老项目成千上万个类要一个个拆模块、理顺requires/exports工作量巨大。生态没跟上大量第三方库早期版本没写module-info放进模块路径会各种告警于是大家干脆继续用 classpath。classpath 仍保留为了兼容JDK 9 同时保留 classpath 模式结果 99% 的项目还是 “JDK 9 跑着 JDK 8 的用法”模块化形同虚设。所以现实里模块化主要被JDK 自身采纳JDK 被拆成java.base、java.sql等模块启动时可以只带用到的模块做瘦身应用层落地很少。学它重点在理解 JDK 内部边界和需要时知道有这能力不必强求给每个项目上模块。三、JShell官方 REPL 终于来了这是 JDK 9 给普通开发者最实在的礼物——一个开箱即用的交互式命令行环境不用再写public static void main就能试代码$ jshell jshell int x 1 1 x 2 jshell List.of(1,2,3).stream().map(n - n*2).toList() $2 [2, 4, 6] jshell /vars // 看所有变量 jshell /methods // 看所有方法 jshell /edit 1 // 编辑第 1 段适用场景快速验证 API 用法、现场算个表达式、教学演示。配合/save/open还能把片段存成脚本。虽然不如 IDE 强大但胜在零依赖、随用随走。四、接口私有方法JDK 8 给了default方法JDK 9 又补上接口私有方法让多个default方法能抽取公共逻辑而不暴露给外部interfaceLogger{defaultvoidinfo(Strings){log(INFO,s);}defaultvoidwarn(Strings){log(WARN,s);}privatevoidlog(Stringlevel,Strings){// 接口内部的私有方法System.out.println([level] s);}}五、Stream 与集合的小增强JDK 9 给集合和 Stream 加了几个实用方法// 工厂方法不可变集合一行搞定JDK 8 还要 Arrays.asList 包装ListStringlistList.of(a,b,c);SetIntegersetSet.of(1,2,3);MapString,IntegermapMap.of(a,1,b,2);// Stream 新增Stream.ofNullable(maybeNull).forEach(System.out::println);// 空值直接跳过Stream.iterate(0,n-n10,n-n1);// 带终止条件的迭代ListIntegertakenlist.stream().takeWhile(n-n3).toList();// 遇到不满足就停注意List.of返回的是不可变集合调用add会抛UnsupportedOperationException——这是不可变优先理念的开始比Collections.unmodifiableList更彻底后者只是包装原 list 还能改。六、其他值得知道的变化特性说明多版本 JAR同一个 JAR 可在不同 JDK 下提供不同 class进程 API 增强ProcessHandle能拿 PID、父进程、子进程新版 HTTP/2 客户端孵化叫jdk.incubator.httpJDK 11 转正为java.net.http废弃 Applet / 加强 G1G1 成为默认 GC之前是 Parallel GC紧凑字符串预热String压缩在 9 完成见下篇七、本篇记住的清单JPMS 用module-info.java做强封装 可靠依赖主要被 JDK 自身采纳应用落地少。模块化叫好不叫座迁移贵、生态滞后、classpath 兼容模式还在。JShell 是官方 REPL验证代码零成本。接口可写私有方法给default方法抽公共逻辑。List.of/Set.of/Map.of返回不可变集合比包装更彻底。Stream.ofNullable/iterate(带终止)/takeWhile等小增强很实用。JDK 9 起 G1 成默认 GCHTTP/2 客户端进孵化。JDK 9 是底层重构 甜点补给的一版。下一篇看 JDK 10/11一个让代码变短的var和一个决定你升级节奏的 LTS 概念。