🚀 Java 巩固进阶 · 第 30 天
主题:JDK9-11 常用新特性 ------ 语法糖与工具升级
📅 进度概览 :恭喜完成 JDK8 核心特性阶段(25-29 天) !今天学习 JDK9-11 的实用新特性。虽然企业主流仍是 JDK8,但掌握新特性能提升代码简洁度,也是技术视野的体现。
💡 核心价值:
- 代码简洁 :
var类型推断、集合工厂方法,减少样板代码。- 工具升级 :
String新方法解决常见痛点,HttpClient替代老旧HttpURLConnection。- 面试加分:了解 JDK 新版本特性,展现持续学习能力。
- 平滑过渡:为未来升级 JDK17/21 打下基础。
一、JDK9:集合工厂方法 ------ 不可变集合的便捷创建 📦
1. 传统创建方式 vs 工厂方法
java
// ❌ 传统:冗长,可变
List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
// ✅ JDK9+:简洁,不可变(⭐ 推荐用于常量集合)
List<String> list = List.of("A", "B", "C");
Set<String> set = Set.of("X", "Y", "Z");
Map<String, Integer> map = Map.of("a", 1, "b", 2, "c", 3);
2. 关键特性与限制
java
// ✅ 优势:
// 1. 代码极简,一行创建
// 2. 不可变(线程安全)
// 3. 内存优化(内部特殊实现)
// ⚠️ 限制:
// 1. 不能添加/删除/修改元素
list.add("D"); // ❌ 抛 UnsupportedOperationException
// 2. 不能存 null 值
List.of("A", null); // ❌ 抛 NullPointerException
// 3. Map.of 键不能重复
Map.of("a", 1, "a", 2); // ❌ 抛 IllegalArgumentException
3. 可变集合的便捷创建
java
// ✅ 需要可变集合时,结合工厂方法
List<String> mutableList = new ArrayList<>(List.of("A", "B", "C"));
mutableList.add("D"); // ✅ 可以修改
// 或使用 toList()(JDK16+)
List<String> list = Stream.of("A", "B", "C")
.collect(Collectors.toUnmodifiableList()); // JDK10+
二、JDK10:var 局部变量类型推断 🔤
1. var 的核心用法
java
// ✅ 传统写法
String name = "Alice";
List<String> list = new ArrayList<>();
// ✅ var 写法(编译器自动推断类型)
var name = "Alice"; // 推断为 String
var list = new ArrayList<String>(); // 推断为 ArrayList<String>
var num = 10; // 推断为 int
2. 使用限制(⭐ 必知)
java
// ✅ 可以用 var 的场景
var str = "hello";
var list = new ArrayList<>();
var user = new User();
// ❌ 不能用 var 的场景
var x; // ❌ 必须有初始值
var y = null; // ❌ 无法推断类型
int[] arr = {1,2};
var z = arr; // ✅ 可以,但推荐明确类型
// ❌ 不能作为字段、方法参数、返回值
public class Test {
private var name = "Alice"; // ❌ 字段不能用 var
public void method(var x) {} // ❌ 参数不能用 var
public var getValue() {} // ❌ 返回值不能用 var
}
3. 最佳实践建议
java
// ✅ 推荐:类型明显时使用 var
var stream = list.stream();
var map = new HashMap<String, Integer>();
// ❌ 不推荐:降低可读性时
var result = calculate(); // ❌ 不知道 result 是什么类型
var data = service.getData(); // ❌ 类型不明确
// ✅ 原则:var 应该让代码更清晰,而非更模糊
三、JDK11:String 新方法 ------ 解决常见痛点 📝
1. 常用新方法对比
| 方法 | 作用 | 传统写法 | JDK11 写法 |
|---|---|---|---|
isBlank() |
判断空或空白 | `s == null | |
strip() |
去除空白(支持 Unicode) | s.trim() |
s.strip() |
stripLeading() |
去除前导空白 | - | s.stripLeading() |
stripTrailing() |
去除尾部空白 | - | s.stripTrailing() |
repeat(n) |
重复字符串 | String.join("", Collections.nCopies(n, s)) |
s.repeat(n) |
lines() |
按行分割 | s.split("\\r?\\n") |
s.lines() |
2. 实战示例
java
String str = " Hello World \n";
// ✅ isBlank()
System.out.println(str.isBlank()); // false
System.out.println(" ".isBlank()); // true(trim().isEmpty() 做不到)
// ✅ strip() vs trim()
System.out.println("'" + str.strip() + "'"); // 'Hello World'
System.out.println("'" + str.trim() + "'"); // 'Hello World'(不支持 Unicode 空白)
// ✅ repeat()
System.out.println("Abc".repeat(3)); // "AbcAbcAbc"
System.out.println("-".repeat(10)); // "----------"(分隔线神器)
// ✅ lines()
String multiLine = "Line1\nLine2\nLine3";
multiLine.lines().forEach(System.out::println);
四、JDK11:HttpClient ------ 现代 HTTP 客户端 🌐
1. 传统方式 vs HttpClient
java
// ❌ 传统:HttpURLConnection(API 老旧,代码冗长)
URL url = new URL("https://www.baidu.com");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
InputStream in = conn.getInputStream();
// ... 大量样板代码
// ✅ JDK11 HttpClient(简洁、现代、支持异步)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://www.baidu.com"))
.GET()
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode()); // 200
System.out.println(response.body()); // 响应内容
2. 异步请求(非阻塞)
java
// ✅ 异步发送,返回 CompletableFuture
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.github.com/users/octocat"))
.GET()
.build();
client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.thenAccept(System.out::println)
.join(); // 等待完成(生产环境可用 CompletableFuture 编排)
⚠️ 生产建议:
- 简单 HTTP 调用可用 HttpClient
- 复杂场景推荐 Spring
RestTemplate或WebClient- 高并发场景推荐
OkHttp或Apache HttpClient(连接池更完善)
五、🎯 今日实战任务:新特性综合应用
任务 1:集合工厂方法实践
java
/**
* 要求:
* 1. 用 List.of 创建不可变列表(5 个元素)
* 2. 用 Set.of 创建不可变集合(去重测试)
* 3. 用 Map.of 创建不可变映射(5 个键值对)
* 4. 尝试添加元素,观察抛出的异常
*
* 💡 提示:
* 需要可变集合时:new ArrayList<>(List.of(...))
*/
任务 2:var 类型推断练习
java
/**
* 要求:
* 1. 用 var 定义 5 种不同类型的变量(String、List、Map、自定义类、Stream)
* 2. 将 IDEA 鼠标悬停在 var 上,查看推断的实际类型
* 3. 思考:哪些场景用 var 更清晰?哪些场景不适合?
*
* 💡 挑战:
* - 尝试在 for-each 循环中使用 var
* - 尝试在 try-with-resources 中使用 var
*/
任务 3:String 新方法重构
java
/**
* 业务场景:用户输入校验与处理
*
* 要求:
* 1. 用 isBlank() 替代 isEmpty() 校验用户输入
* 2. 用 strip() 替代 trim() 去除空白
* 3. 用 repeat() 生成分隔线(如 50 个"-")
* 4. 用 lines() 处理多行文本输入
*
* 💡 对比:
* 统计重构前后的代码行数差异
*/
任务 4:HttpClient 发送请求
java
/**
* 要求:
* 1. 用 HttpClient 发送 GET 请求到 https://www.baidu.com
* 2. 打印状态码和响应体前 100 个字符
* 3. (进阶)用 sendAsync 发送异步请求
* 4. (进阶)处理请求异常(超时、网络错误)
*
* 💡 提示:
* 需要添加 JDK11+ 依赖或使用 JDK11+ 运行
* 如果网络问题,可用 https://httpbin.org/get 测试
*/
📝 第 30 天 · 核心总结(极简背诵版)
-
集合工厂方法:
javaList.of("A", "B") // 不可变列表 Set.of("X", "Y") // 不可变集合 Map.of("k", 1) // 不可变映射(键不能重复) -
var 类型推断:
✅ 局部变量 + 有初始值 ❌ 字段/参数/返回值 + null 值 原则:类型明显时用,否则明确写类型 -
String 新方法:
javaisBlank() // 空或空白 strip() // 去除空白(支持 Unicode) repeat(n) // 重复 n 次 lines() // 按行分割 -
HttpClient:
javaHttpClient.newHttpClient() send() // 同步 sendAsync() // 异步(返回 CompletableFuture)
🎉 恭喜!JDK8+ 新特性阶段完结!
📊 第 25-30 天知识复盘:
├─ Lambda 表达式 → 函数式编程基础
├─ Stream 流 → 集合流式处理
├─ Optional → 空值安全处理
├─ 接口新特性 → default/static 方法
├─ 时间 API 进阶 → 时区与时间戳
└─ JDK9-11 特性 → 语法糖与工具升级
🚀 下一阶段预告:设计模式与注解(第 31-36 天)
📅 第 31 天:设计模式基础(单例、工厂)
📅 第 32 天:设计模式(建造者、原型)
📅 第 33 天:设计模式(代理、装饰器)
📅 第 34 天:注解基础
📅 第 35 天:注解与反射结合
📅 第 36 天:Lombok 实战