JDK 11 新特性详解

📅 2026/7/16 0:12:34 👁️ 阅读次数 📝 编程学习
JDK 11 新特性详解

JDK 11 新特性详解

JDK 11 于2018年9月25日正式发布,是继 JDK 8 之后的第二个长期支持(LTS)版本,也是 Oracle 改变 JDK 许可模式后的第一个版本。JDK 11 包含大量重要特性:Lambda 参数 var、String 新方法、正式 HTTP Client API、Flight Recorder、ZGC、Epsilon GC、单文件源码启动、TLS 1.3 支持等,是一次内容极其丰富的 LTS 升级。


目录

  1. Lambda 参数 var 注解
  2. String 新方法
  3. 文件读写新方法
  4. 集合新方法
  5. Optional 新方法
  6. HTTP Client API(正式)
  7. Launch Single-File Source Code
  8. Flight Recorder(JFR)
  9. ZGC(实验性)
  10. Epsilon GC
  11. Shenandoah GC(实验性)
  12. TLS 1.3 支持
  13. Unicode 10 支持
  14. 移除 Java EE 和 CORBA 模块
  15. Nashorn JavaScript 引擎废弃
  16. 动态 CDS 归档
  17. 其他重要特性
  18. JDK 11 特性总览表

1. Lambda 参数 var 注解

1.1 概述

JDK 11 允许在 Lambda 表达式的参数上使用var关键字(JEP 323),主要目的是让开发者能够为 Lambda 参数添加注解。

核心规则

  • 所有 Lambda 参数必须同时使用var或同时不使用
  • 不能混合使用var和显式类型
  • var在 Lambda 中仅用于注解,类型推断行为不变

1.2 代码案例

// ============ 1. Lambda 参数使用 var ============// JDK 10 及之前:无法为 Lambda 参数添加注解// (s) -> s.length() // 无法添加 @NonNull 等注解// JDK 11:可以为 Lambda 参数添加注解(@NonNullvars)->s.length()// 多个参数(varx,vary)->x+y// ============ 2. 注解示例 ============importjava.lang.annotation.*;@Target(ElementType.TYPE_USE)@Retention(RetentionPolicy.RUNTIME)@interfaceNonNull{}@Target(ElementType.TYPE_USE)@Retention(RetentionPolicy.RUNTIME)@interfaceEmail{}// 使用注解List<String>names=List.of("Alice","Bob","Charlie");// 为 Lambda 参数添加注解names.stream().map((@NonNullvarname)->name.toUpperCase()).forEach(System.out::println);// 多个参数names.stream().sorted((@NonNullvara,@NonNullvarb)->a.compareTo(b)).forEach(System.out::println);// ============ 3. 规则:必须统一使用 var ============// ✅ 正确:全部使用 var(varx,vary)->x+y// ✅ 正确:全部不使用 var(x,y)->x+y// ❌ 错误:混合使用// (var x, y) -> x + y // 编译报错// (var x, String y) -> x + y // 编译报错// ============ 4. 实际应用场景 ============// 静态分析工具(如 Checker Framework)List<String>inputs=List.of("hello","world");List<Integer>lengths=inputs.stream().map((@NonNullvars)->s.length()).collect(Collectors.toList());// 自定义验证inputs.stream().filter((@Emailvaremail)->email.contains("@")).forEach(System.out::println);// ============ 5. 对比方法引用 ============// 当不需要注解时,方法引用更简洁names.stream().map(String::toUpperCase)// 推荐.forEach(System.out::println);// 需要注解时才使用 varnames.stream().map((@NonNullvars)->s.toUpperCase()).forEach(System.out::println);

2. String 新方法

2.1 概述

JDK 11 为String类新增了多个实用方法(JEP 329 的一部分),大幅增强了字符串处理能力。

新增方法一览

方法说明
isBlank()判断是否为空或只包含空白字符
lines()按行分割为 Stream
strip()去除首尾空白(支持 Unicode)
stripLeading()去除首部空白
stripTrailing()去除尾部空白
repeat(int)重复字符串指定次数

2.2 代码案例

// ============ 1. isBlank() — 判断是否为空或只包含空白 ============"".isBlank();// true" ".isBlank();// true(空格)"\t\n".isBlank();// true(制表符+换行)" a ".isBlank();// false"hello".isBlank();// false// 对比 isEmpty()"".isEmpty();// true" ".isEmpty();// false(有空格,不为空)" ".isBlank();// true(但全是空白)// 实际应用:验证用户输入StringuserInput=" ";if(userInput.isBlank()){System.out.println("输入不能为空或只包含空白");}// ============ 2. lines() — 按行分割为 Stream ============Stringmultiline="line1\nline2\nline3\nline4";// 返回 Stream<String>List<String>lines=multiline.lines().collect(Collectors.toList());// ["line1", "line2", "line3", "line4"]// 支持 \n, \r, \r\nStringmixed="line1\nline2\rline3\r\nline4";mixed.lines().forEach(System.out::println);// 实际应用:处理多行配置Stringconfig=""" server.host=localhost server.port=8080 server.timeout=30 """;Map<String,String>configMap=config.lines().filter(line->!line.isBlank()).map(line->line.split("=",2)).filter(parts->parts.length==2).collect(Collectors.toMap(parts->parts[0].trim(),parts->parts[1].trim()));// {server.host=localhost, server.port=8080, server.timeout=30}// 实际应用:过滤空行Stringtext="Hello\n\nWorld\n\nJava";List<String>nonEmptyLines=text.lines().filter(line->!line.isBlank()).collect(Collectors.toList());// ["Hello", "World", "Java"]// ============ 3. strip() — 去除首尾空白(Unicode 感知) ============// strip() 去除所有 Unicode 空白字符" hello ".strip();// "hello""\t hello \n".strip();// "hello""\u2000hello\u2000".strip();// "hello"(Unicode 空白)// stripLeading() — 只去除首部" hello ".stripLeading();// "hello "// stripTrailing() — 只去除尾部" hello ".stripTrailing();// " hello"// 对比 trim()// trim() 只去除 ASCII 空白(code <= U+0020)// strip() 去除所有 Unicode 空白(Character.isWhitespace)StringunicodeSpace="\u2000hello\u2000";// Unicode 空白unicodeSpace.trim();// "\u2000hello\u2000"(不去除,不是 ASCII 空白)unicodeSpace.strip();// "hello"(去除,是 Unicode 空白)// 实际应用:清理用户输入StringrawInput=" \t Alice \n";StringcleanInput=rawInput.strip();// "Alice"// ============ 4. repeat(int) — 重复字符串 ============"ha".repeat(3);// "hahaha""-".repeat(10);// "----------""abc".repeat(0);// ""(重复0次为空)"hello".repeat(1);// "hello"(重复1次不变)// 实际应用:生成表格分隔线intwidth=50;Stringseparator="=".repeat(width);// "=================================================="// 实际应用:生成缩进intindent=4;Stringindentation=" ".repeat(indent);// " "// 实际应用:生成进度条intprogress=7;inttotal=10;Stringbar="█".repeat(progress)+"░".repeat(total-progress);// "███████░░░"// 实际应用:填充字符串到固定长度StringpadRight(Strings,intlength){returns+" ".repeat(Math.max(0,length-s.length()));}StringpadLeft(Strings,intlength){return" ".repeat(Math.max(0,length-s.length()))+s;}// ============ 5. 综合应用 ============// 处理 CSV 文件Stringcsv=""" name,age,city Alice,25,Beijing Bob,30,Shanghai Charlie,20,Guangzhou """;List<Map<String,String>>records=csv.lines().filter(line->!line.isBlank())// 过滤空行.skip(1)// 跳过表头.map(line->line.split(",")).filter(parts->parts.length==3).map(parts->Map.of("name",parts[0].strip(),