深入学习Java 17 LTS版本的重要新特性:密封类、记录类、模式匹配、文本块等现代Java编程特性
Java 17是继Java 11之后的第二个长期支持(LTS)版本,于2021年9月发布。作为LTS版本,Java 17将获得长期的支持和维护,是企业级应用的理想选择。
Java 17引入了许多重要的新特性,这些特性不仅提高了开发效率,还增强了代码的可读性和安全性。主要新特性包括:
密封类是Java 17中引入的一个重要特性,它允许开发者限制哪些类可以继承或实现某个类或接口。这提供了比传统的final关键字更灵活的继承控制。
public sealed class Shape permits Circle, Rectangle, Triangle {
protected final String name;
protected Shape(String name) {
this.name = name;
}
public abstract double getArea();
public String getName() {
return name;
}
}
final class Circle extends Shape {
private final double radius;
public Circle(double radius) {
super("圆形");
this.radius = radius;
}
@Override
public double getArea() {
return Math.PI * radius * radius;
}
public double getRadius() {
return radius;
}
}
final class Rectangle extends Shape {
private final double width;
private final double height;
public Rectangle(double width, double height) {
super("矩形");
this.width = width;
this.height = height;
}
@Override
public double getArea() {
return width * height;
}
}
non-sealed class Triangle extends Shape {
private final double base;
private final double height;
public Triangle(double base, double height) {
super("三角形");
this.base = base;
this.height = height;
}
@Override
public double getArea() {
return 0.5 * base * height;
}
}
记录类是Java 14引入并在Java 17中稳定的特性,它提供了一种简洁的方式来创建不可变的数据载体类。记录类自动生成构造器、访问器方法以及equals、hashCode和toString方法。
public record Person(String name, int age, String email) {
// 紧凑构造器 - 用于验证和规范化
public Person {
Objects.requireNonNull(name, "姓名不能为空");
Objects.requireNonNull(email, "邮箱不能为空");
if (age < 0 || age > 150) {
throw new IllegalArgumentException("年龄必须在0-150之间");
}
if (!email.contains("@")) {
throw new IllegalArgumentException("邮箱格式不正确");
}
}
// 自定义方法
public boolean isAdult() {
return age >= 18;
}
public String getDisplayName() {
return isAdult() ? name + " (成年)" : name + " (未成年)";
}
// 静态工厂方法
public static Person of(String name, int age, String email) {
return new Person(name, age, email);
}
}
// 嵌套记录类
record Address(String street, String city, String zipCode, String country) {
public String getFullAddress() {
return String.format("%s, %s %s, %s", street, city, zipCode, country);
}
}
// 使用示例
class RecordDemo {
public static void main(String[] args) {
Person person = new Person("张三", 28, "zhangsan@example.com");
System.out.println("姓名: " + person.name());
System.out.println("年龄: " + person.age());
System.out.println("邮箱: " + person.email());
System.out.println("是否成年: " + person.isAdult());
System.out.println("显示名称: " + person.getDisplayName());
Address address = new Address("中关村大街1号", "北京", "100080", "中国");
System.out.println("完整地址: " + address.getFullAddress());
}
}
模式匹配是Java中一个强大的特性,它简化了类型检查和转换的代码。Java 17中的模式匹配主要体现在instanceof操作符和switch表达式中。
public class PatternMatchingExample {
public static void processObject(Object obj) {
// 传统方式
if (obj instanceof String) {
String str = (String) obj;
System.out.println("字符串长度: " + str.length());
}
// Java 17模式匹配方式
if (obj instanceof String str) {
System.out.println("字符串长度: " + str.length());
} else if (obj instanceof Integer num) {
System.out.println("整数平方: " + (num * num));
} else if (obj instanceof List> list) {
System.out.println("列表大小: " + list.size());
}
}
}
public class SwitchPatternMatching {
public static String analyzeObject(Object obj) {
return switch (obj) {
case null -> "对象为null";
case String s -> "字符串: \"" + s + "\", 长度: " + s.length();
case Integer i when i > 0 -> "正整数: " + i;
case Integer i when i < 0 -> "负整数: " + i;
case Integer i -> "零: " + i;
case List> list when list.isEmpty() -> "空列表";
case List> list -> "非空列表,大小: " + list.size();
default -> "其他类型: " + obj.getClass().getSimpleName();
};
}
// 与密封类结合使用
public static String describeShape(Shape shape) {
return switch (shape) {
case Circle c -> String.format("圆形: 半径=%.2f, 面积=%.2f",
c.getRadius(), c.getArea());
case Rectangle r -> String.format("矩形: 宽度=%.2f, 高度=%.2f, 面积=%.2f",
r.getWidth(), r.getHeight(), r.getArea());
case Triangle t -> String.format("三角形: 底边=%.2f, 高度=%.2f, 面积=%.2f",
t.getBase(), t.getHeight(), t.getArea());
};
}
}
文本块是Java 15引入的特性,它允许开发者创建多行字符串字面量,而无需使用大量的转义字符和字符串连接操作。
public class TextBlockExample {
public static void demonstrateTextBlocks() {
// 传统方式创建HTML
String traditionalHtml = "\n" +
" \n" +
" 页面标题 \n" +
"
\n" +
" \n" +
" 欢迎使用Java 17
\n" +
" \n" +
"";
// 使用文本块创建HTML
String textBlockHtml = \"\"\"
页面标题
欢迎使用Java 17
\"\"\";
// JSON示例
String jsonData = \"\"\"
{
"name": "张三",
"age": 28,
"address": {
"street": "中关村大街1号",
"city": "北京",
"zipCode": "100080"
},
"hobbies": ["编程", "阅读", "旅行"]
}
\"\"\";
System.out.println("HTML内容:");
System.out.println(textBlockHtml);
System.out.println("\nJSON数据:");
System.out.println(jsonData);
}
}
下面是一个综合展示Java 17新特性的完整示例:
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Random;
public class Java17FeaturesDemo {
public static void main(String[] args) {
System.out.println("🚀 欢迎使用Java 17新特性演示程序!");
// 使用文本块创建JSON模板
String jsonTemplate = \"\"\"
{
"timestamp": "%s",
"features": [
{
"name": "Sealed Classes",
"description": "限制类的继承层次结构"
},
{
"name": "Record Classes",
"description": "简洁的不可变数据载体"
}
]
}
\"\"\";
String currentTime = LocalDateTime.now()
.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
String json = jsonTemplate.formatted(currentTime);
System.out.println("生成的JSON:");
System.out.println(json);
// 使用记录类
List features = List.of(
new FeatureInfo("Sealed Classes", "JEP 409", 17, true),
new FeatureInfo("Record Classes", "JEP 395", 14, true),
new FeatureInfo("Text Blocks", "JEP 378", 15, true)
);
System.out.println("\n=== Java新特性列表 ===");
features.forEach(feature -> {
System.out.println(feature.getDescription());
});
// 使用模式匹配
Object[] testData = {
"Java 17 LTS",
features.size(),
features,
new Random().nextDouble()
};
System.out.println("\n=== 模式匹配处理 ===");
for (Object data : testData) {
String result = analyzeData(data);
System.out.println(result);
}
}
private static String analyzeData(Object data) {
return switch (data) {
case String s when s.contains("Java") -> "Java相关字符串: " + s;
case String s -> "普通字符串: " + s;
case Integer i when i > 10 -> "大整数: " + i;
case Integer i -> "小整数: " + i;
case List> list when !list.isEmpty() ->
"非空列表,包含 " + list.size() + " 个元素";
case List> list -> "空列表";
case Double d -> "浮点数: " + String.format("%.2f", d);
default -> "未知类型: " + data.getClass().getSimpleName();
};
}
}
// 记录类定义
record FeatureInfo(String name, String jep, int introducedVersion, boolean isStable) {
public String getDescription() {
String status = isStable ? "稳定" : "预览";
return String.format("📋 %s (%s) - Java %d引入 [%s]",
name, jep, introducedVersion, status);
}
}