gitbook/深入剖析Java新特性/docs/467973.md
2022-09-03 22:05:03 +08:00

103 lines
7.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 用户故事 | 保持好奇心,积极拥抱变化
你好我是贾慧鑫目前是蔚来汽车的一名后端开发工程师平时主要使用Java语言。
9月份JDK 17正式版发布作为Java的又一长期版本最近我们的新项目也在尝试将JDK 11升级到17。恰巧就在这时候我看到了范学雷老师推出的《深入剖析 Java 新特性》,于是毫不犹疑地订阅了。
我认为作为一名研发工程师应该保持一颗好奇心积极拥抱技术的变化不断地去学习和迭代自己的知识。接下来我想跟大家分享一下工作以来我学习和使用Java的一些心得体会以及这门课程对我的帮助。
## 学习Java的心得
从Java 8开始Java语言正式引入了函数式编程。Stream和Lambda的结合极大地简化了我们在Java7中对集合类的操作。现在再看Java 7会有种回不去的感觉。因为相比之下用Java 7编写的代码又复杂又冗余。如果你还用过Java 11或者Java 17相信这种感觉会更强烈。
而且Java语言也在不断借鉴其他编程语言让代码变得更加简洁高效。下面我通过一个例子来展示一下不同 Java 版本的变化。
```plain
// 假如给定一个由数字1234构成的List要求把元素都值都扩大一倍
// java8
List<Integer> res = initList.stream().map(i -> i * 2).collect(Collectors.toList());
// java11
var res = initList.stream().map(i -> i * 2).collect(Collectors.toUnmodifiableList());
// java17
var res = initList.stream().map(i -> i * 2).toList();
```
首先从代码的样式来看Java 17的版本无疑是最简洁的。另外Java语言在函数式编程方面对于不可变数据的支持也更完善了。比方说Java 8的Collectors.toList()返回的只是一个可变的List在Java 11中就新增了Collectors.toUnmodifiableList()方法支持我们返回不可变的List而在Java 17中我们直接通过toList就能返回不可变的List了。
**不可变数据可以让开发更加简单、可回溯、测试友好它减少了很多可能的副作用也就是说减少了Bug的出现**。尤其是针对并发编程方面,我们应该多使用函数式编程和不可变数据来实现我们的代码逻辑,尽量避免加锁带来的负载逻辑和系统开销。
在平时的工作中,我也尽量去编写纯函数,使用不可变的数据,这样做为我消除了很多不必要的问题。我想用我写的代码来举个例子:
```plain
// lombok是我们现在web开发常用的扩展包其中setter是一个可变操作我们可以把它在配置文件中禁用掉通过其它方式来替代需要setter的场景
lombok.setter.flagUsage = error
lombok.data.flagUsage = error
// 声明
@With
@Getter
@Builder(toBuilder = true)
@AllArgsConstructor(staticName = "of")
@NoArgsConstructor(staticName = "of")
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
public class Model() {
String id;
String name;
String type;
}
// 构建Model
var model_01 = Model.of("101", "model_01", "model");
// 构建空Model
var model_02 = Model.of();
// 构建指定参数的Model
var model_03 = Moder.toBuilder().id("301").name("model_03").build();
// 修改Model的一个值通过@With来生成一个全新的model
var model_04 = model_01.withName("model_04");
// 修改多个值,通过@Builder来生成一个全新的model
var model_05 = model_01.toBuilder().name("model_05").type("new_model").build();
```
上面这段代码是我工作中常用的Model类它结合Lombok简化了冗余代码。这段代码使用of()方法构建新对象withXX()方法修改单个参数toBuilder()方法修改多个参数,修改后会返回新的对象。这种代码编写方式保证了数据的不可变性,让我们的开发更加简单、可回溯、测试友好,减少了任何可能的副作用。
## 《深入剖析 Java 新特性》对我的帮助
从今年九月份到现在Java17正式发布这么短的时间内范学雷老师就出了这门课程真的非常棒。《深入剖析 Java 新特性》不仅帮我梳理了Java新特性的条目和使用方法还把为什么会有这项新特性给我们讲了讲这点真的很重要这让我对新特性有了更深的理解。
我之前看其他讲解封闭类的文章就一直不理解Java这么多年都用过来了为什么还需要封闭类这东西呢但范老师在关于封闭类这一讲里就举了一个形状的案例。我才知道原来以前类的设计要么是全开放要么是全封闭的。它缺少中间的可控状态这让我茅塞顿开对这个新特性有了新的理解。虽然这个封闭类在我编写业务代码时不常用到但是在编写公共工具类的时候可以增加代码的可控性确实是一个不错的选择。
在档案类这一讲我们看到Java在构建不可变对象的路上带我们又向前走了一步进一步简化了我们的代码实现。刚才我简单描述了一下不可变数据的优势以及结合Lombok的实现方式现在有了Record以后我们就可以把Model都交给Record来实现了。
我还去查询了Lombok的版本迭代Lombok在1.18.20版本就对Record进行了支持1.18.22版本开始全面支持JDK17的其他新特性更详细的内容大家可以去Lombok官网看一看。这样一来我们就可以把上面的Model简化为Record来实现
```plain
// 注意:@NoArgsConstructor,@RequiredArgsConstructor,@AllArgsConstructor 只支持class和enum不支持record
@With
@Builder(toBuilder = true)
public record Model(String id, String name, String type) {}
```
在上面这段代码中Record已经极大简化了我们的代码实现。不过我个人有点小遗憾希望Record能有一个默认.of()的对象构造方法,如果能填补上这个空缺,会更符合函数式编程的风格。
另外课程后面的模式匹配和switch表达式都为我们提供了更好的选择让我们的代码更加简洁和灵活。所以如果你还停留在Java 8的话还是尽快学习一下这门课程吧。
## 写在最后
谈到Java相关的函数式编程技术首先应该感谢一下我的mentor他不仅是一位乐于分享知识的技术大神还是Kotlin语言的布道师也经常为开源社区做贡献。如果你对Kotlin语言或者函数式编程感兴趣可以去看一下他的博客[hltj.me](https://hltj.me/)。
感谢极客时间给开发人员提供了这么多专业的、有价值的计算机相关技术而且现在的新课程都结合了最新迭代的相关技术就像范老师的这门课程就在最短的时间内为我们带来了Java最新的特性分析和讲解这对于Java语言从业者无疑是一份宝贵的学习资料。
也期待极客时间在未来可以有更多硬核知识分享,如果能有响应式编程和函数式编程相关的课程,我一定会第一时间购买。
期待你在评论区留言,我们一起讨论更多新特性的知识吧!