03-JDK 10/11 局部变量推断与 LTS:var 到底该怎么用

JDK 9 之后,Oracle 改了发布节奏:从"几年一个大版本"变成"每半年一个功能版"(3 月、9 月各一版)。于是 JDK 10(2018-03)、JDK 11(2018-09)紧跟着来。这两版单体特性不多,但有两个影响深远的东西:var 局部变量推断 ,以及 LTS(长期支持版)制度的确立------后者直接决定了你公司"升到哪、停在哪"。


一、var:类型推断,不是动态类型

JDK 10 最显眼的特性就是 var。它让编译器根据右边的初始值推断变量类型,你不用再写出来:

java 复制代码
// 以前
ArrayList<User> users = new ArrayList<>();
Map<String, List<Integer>> map = new HashMap<>();

// JDK 10+
var users = new ArrayList<User>();
var map = new HashMap<String, List<Integer>>();

但务必澄清一个误解:var 不是 JavaScript 那种动态类型 。var 只是"让我少打几个字",变量类型在编译期就确定了,是强类型、不可变类型。下面这样会编译失败:

java 复制代码
var x = 10;
x = "hello";   // 编译错误:x 已被推断为 int

var 的边界(哪里能用、不能用)

能用 不能用
局部变量(有初始化) 方法参数、返回值、字段
for 循环变量 没有初始化表达式(var x;)
try-with-resources 资源 lambda 参数(JDK 11 起 lambda 参数可隐式类型,但不用 var 关键字)
增强 for 迭代变量 数组初始化器(var a = {1,2} 不行,类型不明)

什么时候该用 var,什么时候不该

经验法则:var 提升可读性就用,损害可读性就不用。

  • 类型在右手一目了然时(构造器、List.of),用 var 更清爽。
  • 类型不明显时(方法返回值、魔法数字 var x = compute()),老老实实写类型,否则读代码要回跳找声明。
java 复制代码
var list = new ArrayList<String>();   // 好:类型一眼看出
var result = service.query();          // 差:得去查 query 返回啥

二、LTS 制度:为什么"升到 11 还是 8"是个真问题

这是 JDK 10/11 里比 var 重要十倍的事。Oracle 的新规则:

  • 每 6 个月一个功能版 ,但只有每三年一个版本是 LTS(Long-Term Support),会得到多年的安全与 bug 修复。
  • JDK 8 是事实上的 LTS(虽早于此制度,但长期维护)。
  • JDK 11 是第一个按新制度发布的 LTS,接着是 17、21......
  • 非 LTS 版本(10、12、13、14、15、16、18、19、20 等)只有半年支持,很快 EOL。

这意味着企业升级策略变成:在 LTS 之间跳跃(8 → 11 → 17 → 21),而不是追每个小版本。选 LTS 的理由是------云厂商、Spring、中间件都只对 LTS 做充分验证;选非 LTS 等于自己当小白鼠。

一句话决策:生产系统优先盯 LTS。2026 年的今天,新项目起点建议 21(最新 LTS);老系统至少升到 17。


三、JDK 11 的其他硬货

JDK 11 作为 LTS,攒了不少实用特性:

1. 单文件源码直接运行

不用先 javac 再 java,直接 java Hello.java 就能跑(编译器在内存里编译后执行)。小脚本、教学 demo 省一步。

2. 全新的 HTTP 客户端(转正)

JDK 9 孵化的 jdk.incubator.http 在 11 转正为 java.net.http,支持 HTTP/2、WebSocket,API 比老 HttpURLConnection 现代得多:

java 复制代码
HttpClient client = HttpClient.newHttpClient();
HttpRequest req = HttpRequest.newBuilder()
    .uri(URI.create("https://api.example.com/user"))
    .header("Accept", "application/json")
    .build();
HttpResponse<String> resp = client.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.statusCode() + " -> " + resp.body());

// 异步也很自然
client.sendAsync(req, HttpResponse.BodyHandlers.ofString())
    .thenApply(HttpResponse::body)
    .thenAccept(System.out::println);

3. 字符串增强

java 复制代码
"  hello  ".strip();        // 去首尾空白(识别 Unicode 空白,比 trim 更准)
"  hello  ".stripIndent();  // 去公共缩进(配合文本块,见 12/13 篇)
"a".repeat(3);              // "aaa"
"java".isBlank();           // false;"  ".isBlank() true(全空白判断)

4. 集合与 Optional 小补

  • List.of / Set.of / Map.of 在 9 引入,11 稳定。
  • Optional 加 isEmpty()、ifPresentOrElse、or、stream()。
  • String 底层完成紧凑化:纯 Latin-1 字符用 1 字节存,内存直接省一半(9 引入,11 打磨)。

5. 性能与 GC

  • ZGC(实验) 和 Epsilon(无操作 GC) 引入:ZGC 目标亚毫秒停顿、支持超大堆;Epsilon 用于测试/极短生命周期场景。
  • G1 持续调优,成为实至名归的默认主力。

6. 移除了什么

JDK 11 删掉了 Java EE 和 CORBA 模块 (java.xml.bind 等 JAXB 被移除),也删了 javafx(改由 OpenJFX 独立维护),还去掉了 Nashorn JavaScript 引擎(后续版彻底移除)。这意味着老项目如果从 JDK 8 升级到 11,若用到 javax.xml.bind 等,必须手动加第三方依赖(如 jakarta.xml.bind),这是迁移第一大坑。


四、本篇记住的清单

  1. var 是编译期类型推断,仍是强类型,不能用于参数/返回值/字段。
  2. var 提升可读性就用,类型不明时老实干写类型。
  3. LTS 制度:8/11/17/21 是 LTS;企业只在 LTS 间跳跃升级。
  4. JDK 11 可 java X.java 直接跑单文件源码。
  5. java.net.http 全新 HTTP 客户端,支持 HTTP/2 与异步。
  6. 字符串 strip/isBlank/repeat 比 trim 更现代。
  7. JDK 11 移除 JAXB/CORBA/JavaFX/Nashorn------8 升 11 迁移的第一类雷。
  8. ZGC、Epsilon 在 11 进场(实验)。

理解了 var 和 LTS,你就掌握了"现代 Java 升级节奏"的开关。下一篇 JDK 12/13:var 之后,文本块和 switch 表达式又让代码清爽了一截。

相关推荐
金銀銅鐵2 小时前
带您看懂字节码指令(三):同一行加法,为什么有四种指令
java·jvm
文丑颜不良啊6 小时前
LeetCode2821~2840题目解析
java·leetcode
apcipot_rain7 小时前
C++转Java日记(10)
java·开发语言
简 洁 冬冬7 小时前
泛型方法写法全面辨析:从「能编译」到「能跑」到「能用」
java·泛型
LGL6030A8 小时前
Java学习历程31——初识Spring Boot
java·spring boot·学习
Lansonli9 小时前
大数据Spark(八十八):Spark任务资源之Standalone集群测试
java·服务器·spark
budingxiaomoli10 小时前
Spring AOP
java·spring·java-ee
特立独行的猫A10 小时前
Ionic + 仓颉语言的 cj-tauri 开发框架实战:开发精美移动端 APP
java·后端·python
nice_lcj52010 小时前
LRU 缓存入门:它是什么、怎么用、面试怎么手写
java·数据结构·缓存·面试·lru
文丑颜不良啊11 小时前
LeetCode2741~2760题目解析
java·leetcode