俗话说得好:你发任你发,我用 Java 8
,但不得不说新版本 JDK
中引入的一些特性让人眼前一亮,在新项目中可以考虑采用新版 JDK
进行开发,并且 Spring Boot 3
的最低支持版本也需 JDK 17
了,又给了你一个新项目抛弃 Java 8
的理由。
本文即介绍不同版本 JDK 中我用的较多的新特性。
一、安装配置
1. JDK下载
在开始直接先进入 Oracle JDK
官网下载相应的 JDK
版本,为了更方便同时安装多个版本,建议下载 zip
格式解压即享,官网直达。
新版 JDK
并没有自带 jre
目录,因此我们需要手动编译生成,进入上述解压后的文件执行下述命令。
# Windwos 下执行
binjlink.exe --module-path jmods --add-modules java.desktop --output jre
# Linux 下执行
bin/jlink --module-path jmods --add-modules java.desktop --output jre
2. IDEA配置
若要在 IDEA
中指定工程的 JDK
版本,需要完成下述两个步骤。
项目配置在 IDEA
左上角 File
选择 Project Structure
按照下图修改,添加上述解压的 JDK
目录即可。同时可以选择图中的 modules
为工程的每个模块手动设置 JDK
版本。
编译配置在 IDEA
中左上角 File
选择 Settings
按照下图修改编译版本。
3. Maven配置
- 文件配置在
Maven
工程的POM
文件中添加下述属性配置用于指定JDK
依赖版本,完成后刷新配置即可。xml<properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> </properties>
- 编译配置在通过
Maven
进行install
时若提示警告:源发行版17需要目标发行版17
等类似信息时是因为IDEA
中配置Maven
版本与实际项目的版本不匹配,需要手动在IDEA
配置中修改。在IDEA
中左上角File
选择Settings
按照下图修改编译版本。
二、JDK 9
1. 集合
在 JDK 9
中为 List
等集合提供了 of()
初始化方式,实现更便捷的默认值初始化。
相应的使用示例如下:
public void collectionDemo() {
Set<Integer> set = Set.of(1, 2, 3);
System.out.println("Set: " + set);
List<Integer> list = List.of(1, 2, 3);
System.out.println("List: " + list);
Map<Integer, String> map = Map.of(1, "1", 2, "2", 3, "3");
System.out.println("Map: " + map);
}
2. Stream
在 JDK 8
中引入了全新特性 stream
,而在 JDK 9
中为 stream
添加了两个全新接口 takeWhile()
与 dropWhile()
,具体信息如下:
方法 | 作用 |
---|---|
takeWhile() | 当满足提供的条件时停止。 |
dropWhile() | 与 takeWhile 相反,当满足提供的条件时开始。 |
在使用 takeWhile()
与 dropWhile()
接口前,可通过 stream
的 sorted()
接口对目标集合按照一定规则进行排序,使得目标集合呈现一定的线性排列,从而更好的应用上述两类方法。
public void streamDemo() {
List<Integer> list = new ArrayList<>();
for (int i = 1; i < 5; i++) {
list.add(i);
}
List<Integer> list1 = list.stream()
// Break when "t > 3"
.takeWhile(t -> t < 3)
.toList();
// list1: 1, 2
System.out.println("List takeWhile: " + list1);
List<Integer> list2 = list.stream()
// Start from "t > 3"
.dropWhile(t -> t < 3)
.toList();
// list2: 3, 4
System.out.println("List dropWhile: " + list2);
}
3. 私有接口
在 JDK 8
引入了默认接口方法与静态接口方法,而在 JDK 9
提供了私有接口方法以达到代码复用的目的。
通过 private
声明私有接口方法,其仅能在当前接口类中使用。
public interface Calculator {
default void sayHello(String message) {
saySomething("Hello World!");
}
default void sayGoodbye(String message) {
saySomething("Goodbye!");
}
/**
* 私有接口方法
*/
private void saySomething(String message) {
System.out.println("Call private interface, message: " + message);
}
}
4. 其它特性
G1
垃圾收集器在年轻代将不会回收Humongous
块的对象空间。
三、JDK 11
1. var定义
在 JDK 11
中引入了 var
关键字实现泛化定义,在声明声明对象时无需显式指定对象类型,由系统自动识别。
如下中通过 var
定义了 int
变量与 String
变量。
public void varDemo() {
var a = 10;
System.out.println("a: " + a);
var str = "hello world!";
System.out.println("Str: " + str);
}
2. 字符方法
在 JDK 11
中同时为字符串新增了一系列常用接口,具体描述如下:
方法 | 作用 |
---|---|
isBlank() | 判断字符串是否为空或内容皆为空格。 |
isEmpty() | 判断字符串长度是否大于 0。 |
repeat(n) | 用于重复拼接字符串内容。 |
上述方式的相应示例如下:
public void strDemo() {
var msg = "";
System.out.println("isBlank: " + msg.isBlank());
System.out.println("isEmpty: " + msg.isEmpty());
var str = "ibudai";
// ibudaiibudai
System.out.println("repeat: " + str.repeat(2));
}
3. 其它特性
- 完善
HTTP
客户端API
的标准化,提供更加便捷的操作HTTP
请求,但我们更多使用的为OkHttp
等封装类库,使用JDK
自带的场景较少,这里不做详细介绍。 - 正式引入
ZGC(Z Garbage Collector)
垃圾回收器,其为一种低停顿垃圾回收器,可以更好地利用内存,减少停顿时间。
四、JDK 13
1. switch
在 JDK 13
中为 switch
引入了全新的表达式语法,并在 JDK 14
中进一步得到完善。
下面通过一个具体的示例演示 switch
表达式的作用。
public void switchDemo() {
int num = 1;
int value = switch (num) {
case 1, 2 -> num += 1;
case 3, 4 -> num += 2;
default -> num += 3;
};
System.out.println(value);
}
上述的表达式对应的传统 switch
定义方式如下:
public void switchDemo() {
int num = 1;
int value = 0;
switch (num) {
case 1:
case 2:
value = num + 1;
case 3:
case 4:
value = num + 2;
default:
value = num + 3;
};
System.out.println(value);
}
2. yield
在 switch
表达式中每个 case
对应的内容为一个函数, break
无法在此使用用于结束分支。因此 JDK 13 引入全新关键字 yield
用于结束分支并返回结果。
yield
关键字作用类似于 break
于 return
的结合,但 break
仅有中断效果没有返回结果功能,而 return
是结束整个方法块但 yield
仅结束对应的 case
分支。
相应的 yield
关键字使用示例如下:
public void switchDemo() {
int num = 1;
int value = switch (num) {
case 1, 2 -> {
yield num + 1;
}
case 3, 4 -> {
yield num + 2;
}
default -> {
yield num + 3;
}
};
System.out.println(value2);
}
3. 字符块
在 JDK 13
中为字符串引入了新的定义方式,即可通过三个引号 """
声明,从而避免传统的字符冲突需要使用转义字符。
如下 str
对象定义了一个 json
对象,通过 """
即可省略旧版中转义字符的使用,同时也提高了可读性。
public void strDemo() {
String str = """
{
"name": "alex"
}
""";
System.out.println(str);
}
五、JDK 14
1. record
在 JDK 14
中引入新的关键字 record
用于 bean
对象,默认为对象重写了 equals()
, toString()
, hashCode()
方法,并提供便捷的 getter
方法。
相应的 record
使用示例如下,通过 对象.属性
的方式即可实现对象成员变量的访问。
public record User(String id, String name) {
}
public class Jdk14Test {
public void recordDemo() {
User user = new User("123", "Alex");
String id = user.id();
String name = user.name();
System.out.println("id: " + id);
System.out.println("name: " + name);
System.out.println("user: " + user);
}
}
2. 其它特性
新增了低延迟垃圾器,通过 UnlockExperimentalVMOptions
参数指定是否激活。
# ZGC on Windows
-XX:+UnlockExperimentalVMOptions -XX:+UseZGC
# ZGC on macOS
-XX:+UnlockExperimentalVMOptions -XX:+UseZGC
六、JDK 17
1. sealed
在 JDK 17
中引入了新关键词 sealed
与 permits
用于限定类的继承关系。
sealed
关键字可作用于类(class)
或接口(interface)
,通过 permit
关键字指定允许继承的子类,只有被 permits
的类才允许继承类,同时继承的子类也需标注其是否为 sealed
或 non-sealed
。
public sealed class Human permits Student {
private String name;
}
public non-sealed class Student extends Human {
}
// 非法,Teacher 未在 permits 集合中
public class Teacher extends Human {
}
2. switch
在 JDK 17
中为 switch
表达式升级了模式匹配,能够实现更灵活的类型比对判断。
如下为官方文档中提供的示例代码:
public String patternSwitch(Object o) {
return switch (o) {
case Integer i -> String.format("int %d", i);
case Long l -> String.format("long %d", l);
case Double d -> String.format("double %f", d);
case String s -> String.format("String %s", s);
default -> o.toString();
};
}
本站部分资源来源于网络,仅限用于学习和研究目的,请勿用于其他用途。
如有侵权请发送邮件至1943759704@qq.com删除
码农资源网 » 不同版本的 JDK 特性介绍