JDK9-11 新特性
面试提问
"JDK9-11 有哪些重要新特性?"
JDK 9 新特性
1. 模块化系统(JPMS)
// module-info.java
module com.example.myapp {
requires java.sql; // 依赖模块
requires transitive java.logging; // 传递依赖
exports com.example.api; // 导出包
opens com.example.internal to com.example.tests; // 反射访问
uses com.example.Service; // 使用服务
provides Service with ServiceImpl; // 提供服务
}优点:
- 更强的封装性
- 更小的运行时(jlink 定制 JRE)
- 更好的安全性
2. JShell(交互式编程)
jshell> int add(int a, int b) { return a + b; }
jshell> add(1, 2)
$2 ==> 33. 接口私有方法
public interface MyInterface {
default void method1() {
privateMethod(); // 调用私有方法
}
default void method2() {
privateMethod();
}
// 私有方法(JDK 9+)
private void privateMethod() {
System.out.println("Common logic");
}
}4. try-with-resources 增强
// JDK 8:需要在 try 中声明
try (InputStream is = new FileInputStream("file.txt")) {
// ...
}
// JDK 9:可使用已声明的变量
InputStream is = new FileInputStream("file.txt");
try (is) { // 直接使用
// ...
}5. 不可变集合工厂方法
// JDK 8
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
List<String> unmodifiable = Collections.unmodifiableList(list);
// JDK 9+ 工厂方法
List<String> list = List.of("a", "b", "c");
Set<String> set = Set.of("a", "b", "c");
Map<String, Integer> map = Map.of("a", 1, "b", 2);
// 注意:不可变,以下操作抛异常
// list.add("d"); // UnsupportedOperationException6. Stream API 增强
// takeWhile:取到第一个不满足条件的元素
Stream.of(1, 2, 3, 4, 5, 3, 2, 1)
.takeWhile(n -> n < 4)
.forEach(System.out::print); // 1 2 3
// dropWhile:丢弃到第一个不满足条件的元素
Stream.of(1, 2, 3, 4, 5, 3, 2, 1)
.dropWhile(n -> n < 4)
.forEach(System.out::print); // 4 5 3 2 1
// ofNullable:创建可能为空的 Stream
Stream<String> s = Stream.ofNullable(null); // 空流
// iterate:带终止条件
Stream.iterate(1, n -> n < 10, n -> n + 1)
.forEach(System.out::print); // 1 2 3 4 5 6 7 8 97. Optional 增强
// ifPresentOrElse
Optional.of("value").ifPresentOrElse(
v -> System.out.println("有值: " + v),
() -> System.out.println("无值")
);
// or
Optional.empty().or(() -> Optional.of("默认值")); // Optional[默认值]
// stream
Optional.of("value").stream(); // Stream["value"]JDK 10 新特性
1. var 局部变量类型推断
// 编译器自动推断类型
var list = new ArrayList<String>(); // ArrayList<String>
var stream = list.stream(); // Stream<String>
var map = new HashMap<String, Integer>(); // HashMap<String, Integer>
// 注意事项
var a = 1; // int
var b = 1.0; // double
var c = "hello"; // String
var d = List.of(1, 2, 3); // List<Integer>
// 不能使用 var 的场景
// var x; // 错误:必须初始化
// var x = null; // 错误:无法推断类型
// var x = () -> {}; // 错误:Lambda 需要明确类型
// class Field { var x = 1; } // 错误:不能用于字段2. 不可变集合增强
// copyOf:创建不可变副本
List<String> mutable = new ArrayList<>(List.of("a", "b"));
List<String> immutable = List.copyOf(mutable);
// 如果原集合已经是不可变的,直接返回
List<String> original = List.of("a", "b");
List<String> copy = List.copyOf(original); // 返回同一个实例3. Optional 增强
// orElseThrow():无参版本,默认抛 NoSuchElementException
Optional.empty().orElseThrow(); // 抛异常JDK 11 新特性
1. 字符串方法增强
// isBlank:判断空白
" ".isBlank(); // true
"".isBlank(); // true
"hello".isBlank(); // false
// lines:按行分割
"a\nb\nc".lines().forEach(System.out::println);
// strip:去除首尾空白(支持 Unicode)
" hello ".strip(); // "hello"
" hello ".trim(); // "hello"
"\u2000hello\u2000".strip(); // "hello"(Unicode 空白)
"\u2000hello\u2000".trim(); // 不去除 Unicode 空白
// stripLeading / stripTrailing
" hello ".stripLeading(); // "hello "
" hello ".stripTrailing(); // " hello"
// repeat:重复
"ab".repeat(3); // "ababab"2. 文件读写简化
// 读取文件为字符串
String content = Files.readString(Path.of("file.txt"));
// 写入字符串到文件
Files.writeString(Path.of("file.txt"), "Hello World");3. 集合转数组
// JDK 8
List<String> list = List.of("a", "b", "c");
String[] arr = list.toArray(new String[0]);
// JDK 11
String[] arr = list.toArray(String[]::new);4. Lambda 参数使用 var
// 可以使用 var 声明参数
list.stream()
.map((var s) -> s.toUpperCase())
.forEach(System.out::println);
// 可以添加注解
list.stream()
.map((@NonNull var s) -> s.toUpperCase())
.forEach(System.out::println);5. HTTP Client(标准化)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://example.com"))
.build();
// 同步请求
HttpResponse<String> response = client.send(
request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
// 异步请求
client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.thenAccept(System.out::println);版本特性对比
| 特性 | JDK 9 | JDK 10 | JDK 11 |
|---|---|---|---|
| 模块化 | ✅ | - | - |
| var 类型推断 | - | ✅ | ✅ |
| 接口私有方法 | ✅ | - | - |
| 不可变集合工厂 | ✅ | 增强 | - |
| Stream 增强 | ✅ | - | - |
| Optional 增强 | ✅ | ✅ | - |
| 字符串增强 | - | - | ✅ |
| HTTP Client | 孵化 | 孵化 | ✅ 正式 |
| 单文件执行 | - | - | ✅ |
单文件执行(JDK 11)
# 直接执行 Java 文件(无需先编译)
java HelloWorld.java
# 带参数
java HelloWorld.java arg1 arg2面试要点总结
| 问题 | 答案要点 |
|---|---|
| JDK 9 模块化? | module-info.java,更强封装 |
| JDK 10 var? | 局部变量类型推断,必须初始化 |
| JDK 11 字符串? | isBlank、lines、strip、repeat |
| JDK 9 集合工厂? | List.of()、Set.of()、Map.of() |