大家好呀!👋 作为一名Java老司机,今天我要和大家分享如何用Java 17及以上版本写出既优雅又高效的代码。别担心,我会用最简单的方式讲解,保证连小学生都能听懂!😊 这篇文章会很长很详细,但绝对值得你花时间读完哦!🚀
📚 第一章:现代Java新特性快速入门
1.1 var关键字 - 让代码更简洁
还记得以前我们要这样声明变量吗?
String name = "小明";
List hobbies = new ArrayList<>();
现在可以简化为:
var name = "小明"; // 编译器知道这是String类型
var hobbies = new ArrayList(); // 编译器知道这是ArrayList
小贴士:var
不是"动态类型",它只是让编译器帮我们推断类型,编译后类型还是确定的哦!🧐
1.2 文本块(Text Blocks) - 告别丑陋的字符串拼接
以前写多行字符串要这样:
String html = "\n" +
" \n" +
" Hello, world!\n" +
" \n" +
"\n";
现在可以这样优雅:
String html = """
Hello, world!
""";
注意:三个引号"""
必须单独成行,文本块会自动处理缩进,太方便了!🎉
1.3 switch表达式 - 更强大的switch
老式switch:
String dayType;
switch (day) {
case "周一":
case "周二":
case "周三":
case "周四":
case "周五":
dayType = "工作日";
break;
case "周六":
case "周日":
dayType = "周末";
break;
default:
dayType = "未知";
}
新式switch表达式:
String dayType = switch (day) {
case "周一", "周二", "周三", "周四", "周五" -> "工作日";
case "周六", "周日" -> "周末";
default -> "未知";
};
优点:
- 更简洁
- 可以直接返回值
- 使用
->
避免忘记写break
的问题
🛠️ 第二章:集合操作新姿势
2.1 不可变集合 - 安全第一
以前创建不可变集合很麻烦:
List list = new ArrayList<>();
list.add("A");
list.add("B");
list = Collections.unmodifiableList(list);
现在简单多了:
List list = List.of("A", "B"); // 不可变列表
Set set = Set.of("A", "B"); // 不可变集合
Map map = Map.of("A", 1, "B", 2); // 不可变映射
为什么重要:
- 线程安全
- 防止意外修改
- 更清晰的意图表达
2.2 Stream API增强
Java 16引入了Stream.toList()
简化代码:
// 以前
List filtered = list.stream()
.filter(s -> s.length() > 3)
.collect(Collectors.toList());
// 现在
List filtered = list.stream()
.filter(s -> s.length() > 3)
.toList(); // 更简洁!
小测验:你知道.toList()
返回的是可变还是不可变的列表吗?🤔
(答案:不可变的哦!)
🧩 第三章:模式匹配 - 代码更智能
3.1 instanceof模式匹配
老式写法:
if (obj instanceof String) {
String s = (String) obj;
System.out.println(s.length());
}
新模式匹配:
if (obj instanceof String s) { // 自动转换和赋值
System.out.println(s.length());
}
优点:减少样板代码,更易读!
3.2 switch模式匹配(Java 17预览特性)
更强大的模式匹配:
static String formatterPatternSwitch(Object obj) {
return switch (obj) {
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 -> obj.toString();
};
}
未来展望:Java 19将引入更强大的模式匹配,可以匹配嵌套结构!🌟
⚡ 第四章:性能优化技巧
4.1 记录类(Records) - 数据类的终极形态
以前写一个纯数据类要这样:
public final class Person {
private final String name;
private final int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// getters
// equals, hashCode, toString
}
现在用记录类:
public record Person(String name, int age) {}
自动获得:
- 不可变字段
- 公共构造方法
- equals()和hashCode()
- toString()
- getter方法(但叫name()而不是getName())
适用场景:DTO、值对象、纯数据载体
4.2 密封类(Sealed Classes) - 更安全的继承
控制哪些类可以继承:
public sealed class Shape
permits Circle, Square, Rectangle { ... }
public final class Circle extends Shape { ... }
public final class Square extends Shape { ... }
public final class Rectangle extends Shape { ... }
好处:
- 明确类的继承关系
- 配合模式匹配更安全
- 编译器可以检查是否处理了所有情况
🧠 第五章:并发编程新思路
5.1 虚拟线程(Java 19预览) - 轻量级线程
传统线程模型的问题:
// 每个线程对应一个操作系统线程,创建成本高
new Thread(() -> {
// 任务代码
}).start();
虚拟线程:
Thread.startVirtualThread(() -> {
// 任务代码
});
特点:
- 轻量级(一个Java线程可以运行数百万个虚拟线程)
- 由JVM调度,不绑定操作系统线程
- 适合I/O密集型任务
5.2 CompletableFuture增强
Java 9新增的方法:
CompletableFuture future = CompletableFuture.supplyAsync(() -> "Hello")
.thenApplyAsync(s -> s + " World")
.completeOnTimeout("Timeout", 1, TimeUnit.SECONDS) // 超时处理
.orTimeout(2, TimeUnit.SECONDS); // 整体超时
最佳实践:始终指定超时时间,避免永远等待!
🧹 第六章:代码整洁之道
6.1 空指针防御新姿势
Optional的链式调用:
// 以前的多层null检查
if (user != null && user.getAddress() != null && user.getAddress().getCity() != null) {
// ...
}
// 使用Optional
Optional.ofNullable(user)
.map(User::getAddress)
.map(Address::getCity)
.ifPresent(city -> System.out.println("城市: " + city));
注意:不要滥用Optional,它设计用来表示"可能有值",不是用来替代null检查的!
6.2 方法参数校验
Java标准方式:
public void process(String input) {
Objects.requireNonNull(input, "input不能为null");
if (input.length() < 5) {
throw new IllegalArgumentException("input长度至少为5");
}
// ...
}
使用第三方库(如Valibot):
public void process(@NotNull @Size(min=5) String input) {
// 自动校验
}
🎯 第七章:实战案例 - 重构前后对比
案例1:处理用户订单
重构前:
public class OrderProcessor {
public void processOrder(Order order) {
if (order == null) {
throw new IllegalArgumentException("订单不能为空");
}
if (order.getItems() == null || order.getItems().isEmpty()) {
throw new IllegalArgumentException("订单项目不能为空");
}
for (Item item : order.getItems()) {
if (item.getPrice() <= 0) {
throw new IllegalArgumentException("商品价格必须大于0");
}
// 更多校验...
}
// 处理逻辑...
}
}
重构后:
public record Order(List items) {
public Order {
Objects.requireNonNull(items, "订单项目不能为空");
if (items.isEmpty()) {
throw new IllegalArgumentException("订单项目不能为空");
}
}
}
public record Item(String name, BigDecimal price) {
public Item {
Objects.requireNonNull(name, "商品名称不能为空");
Objects.requireNonNull(price, "商品价格不能为空");
if (price.compareTo(BigDecimal.ZERO) <= 0) {
throw new IllegalArgumentException("商品价格必须大于0");
}
}
}
public class OrderProcessor {
public void processOrder(Order order) {
// 不需要校验,因为记录类构造时已经校验
// 直接处理逻辑...
}
}
改进点:
- 使用记录类自动获得不可变性和方法
- 将校验逻辑移到构造函数中
- 业务方法更专注于业务逻辑
🚀 第八章:Java未来版本展望
8.1 Java 20/21即将带来的新特性
- 字符串模板(预览):
String name = "Joan";
String info = STR."My name is \{name}";
- 结构化并发(孵化):
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
Future user = scope.fork(() -> findUser());
Future order = scope.fork(() -> fetchOrder());
scope.join(); // 等待两者完成
scope.throwIfFailed(); // 如果有异常则抛出
// 两个任务都成功完成
return new Response(user.resultNow(), order.resultNow());
}
- 值对象(Value Objects) - 更轻量级的记录类
📝 第九章:最佳实践总结
-
KISS原则:保持简单(Keep It Simple, Stupid)
- 使用
var
简化局部变量声明 - 使用记录类替代样板代码
- 使用
-
防御性编程:
- 使用
Objects.requireNonNull
校验参数 - 优先使用不可变集合
- 使用
-
函数式思维:
- 多用Stream API处理集合
- 避免副作用
-
并发安全:
- 使用不可变对象
- 考虑虚拟线程处理I/O密集型任务
-
代码可读性:
- 使用文本块处理多行字符串
- 使用模式匹配简化条件逻辑
🎓 第十章:学习资源推荐
-
官方文档:
-
书籍推荐:
- 《Java核心技术 卷I》(最新版)
- 《Effective Java》(第三版)
- 《现代Java编程实战》
-
在线学习:
🎉 结语
哇!不知不觉我们已经一起探索了这么多现代Java的优雅编码技巧!😊 从简单的var
关键字到高级的模式匹配,从记录类到虚拟线程,Java正在变得越来越强大、越来越优雅。
记住,写出好代码的关键不是记住所有语法,而是培养良好的编程思维。就像学骑自行车一样,开始可能会摔倒几次,但一旦掌握了平衡,就能自由驰骋啦!🚴
希望这篇文章能成为你Java编程之旅中的一盏明灯。如果觉得有帮助,别忘了分享给你的小伙伴哦!🤗
最后的小测验:你现在能说出至少5个Java 17+的新特性吗?试试看!💪
(答案提示:var、文本块、记录类、密封类、模式匹配、switch表达式…还有很多哦!)
Happy coding!🎯👨💻👩💻