背景

2022 年 Spring 6 和 SpringBoot 3 相继推出。在此之前,Java 社区一直是"新版任你发,我用 Java 8",不管新版本怎么出,很少有人愿意升级。

这一次,Spring 直接来了个大招,Spring 6 和 SpringBoot 3 的最低依赖就是JDK17!跨过 JDK 8 ~ JDK 16,直接升级到 JDK 17。

那么,为什么是 JDK 17 呢?

为什么是 JDK 17

有这么多新版本的 JDK,而且 2022 年还会推出 JDK 18 和 JDK 19,为什么 Spring 选择了 JDK 17 呢?

主要因为它是一个 Oracle 官宣可以免费商用的 LTS 版本。LTS 即 Long Term Support,也就是官方保证会长期支持的版本。

上面这张图是 Oracle 官方给出的对 JDK 提供支持的时间线。可以看得到,JDK 17 最多可以支持到 2029 年 9 月份。按照技术更新迭代的速度,这次免费商用 8 年可谓是良苦用心,为的就是让使用者放心大胆地将 JDK 升级到 JDK 17(不过JDK 8 支持的时间更长,可以延长到 2030 年 12 月,JDK 8可谓是YYDS!)

从 JDK 诞生到现在,还在长期支持的版本主要有 JDK 7、JDK 8 、JDK 11以及 JDK 1。JDK 17 将是继 Java 8 以来最重要的 LTS 版本,是 Java 社区 8 年努力的成果。

一直以来,Java 8 都是 Java 社区心头的痛。Java 8 提供了很多特性,比如Lambda 表达式、Optional 类等,加上 Java 8 超长的支持时间,这些都使得“古老的”JDK 8沿用至今。于是,“以维持稳定性为目标的企业管理层”与“期待拥抱变化的程序猿”之间的拉锯战迟迟无法落下帷幕。不升!成为各大厂心照不宣的选择。

现在,这种平衡或将被打破。因为 Java 届的霸主框架 SpringBoot,选择了最小支持的 Java LTS 版本,就是最新的 Java 17。

那么接下来,让我们看看从 JDK 8 到 JDK 17,Java 社区 8 年努力的成果有哪些?

从 JDK 8 到 JDK 17 的新特性

JDK 9 新特性(2017 年 9 月)

  • 模块化

  • 提供了 List.of()、Set.of()、Map.of() 和 Map.ofEntries() 等工厂方法

  • 接口支持私有方法

  • Optional 类改进

  • 多版本兼容 Jar 包

  • JShell 工具

  • try-with-resources 的改进

  • Stream API 的改进

  • 设置 G1 为 JVM 默认垃圾收集器

  • 支持 HTTP 2.0 和 WebSocket 的 API

重要特性:API 的优化,如支持 HTTP 2 的 Client API、JVM 采用 G1 为默认垃圾收集器。

JDK 10 新特性(2018 年 3 月)

  • 局部变量类型推断,类似 JS 可以通过 var 来修饰局部变量,编译之后会推断出值的真实类型

  • 不可变集合的改进

  • 并行全垃圾回收器 G1,来优化 G1 的延迟

  • 线程本地握手,允许在不执行全局 VM 安全点的情况下执行线程回调,可以停止单个线程,而不需要停止所有线程或不停止线程

  • Optional 新增 orElseThrow() 方法

  • 类数据共享

  • Unicode 语言标签扩展

  • 根证书

重要特性:通过 var 关键字实现局部变量类型推断,使 Java 语言变成弱类型语言、JVM 的 G1 垃圾回收由单线程改成多线程并行处理,降低 G1 的停顿时间。

JDK 11 新特性(2018年 9 月)(LTS 版本)

  • 增加一些字符串处理方法

  • 用于 Lambda 参数的局部变量语法

  • Http Client 重写,支持 HTTP/1.1 和 HTTP/2,也支持 websockets

  • 可运行单一 Java 源码文件,如:java Test.java

  • ZGC:可伸缩低延迟垃圾收集器。ZGC 可以看作是 G1 之上更细粒度的内存管理策略。由于内存的不断分配回收会产生大量的内存碎片空间,因此需要整理策略防止内存空间碎片化。在整理期间需要将对于内存引用的线程逻辑暂停,这个过程被称为“Stop the world”。只有当整理完成后,线程逻辑才可以继续运行。(并行回收)

  • 支持 TLS 1.3 协议

  • Flight Recorder(飞行记录器),基于 OS、JVM 和 JDK 的事件产生的数据收集框架

  • 对Stream、Optional、集合 API 进行增强

重要特性:对于 JDK 9 和 JDK 10的完善,主要是对于 Stream、集合等 API 的增强、新增 ZGC 垃圾收集器。

JDK 12 新特性(2019 年 3 月)

  • Switch 表达式扩展,可以有返回值

  • 新增 NumberFormat 对复杂数字的格式化

  • 字符串支持 transform、indent 操作

  • 新增方法 Files.mismatch(Path, Path)

  • Teeing Collector

  • 支持 unicode 11

  • Shenandoah GC,新增的 GC 算法

  • G1 收集器的优化,将 GC 的垃圾分为强制部分和可选部分,强制部分会被回收,可选部分可能不会被回收,提高GC的效率

重要特性:switch 表达式语法扩展、G1 收集器优化、新增 Shenandoah GC 垃圾回收算法。

JDK 13 新特性(2019 年 9 月)

  • Switch 表达式扩展,Switch 表达式增加 yield 关键字用于返回结果,作用类似于 return,如果没有返回结果则使用 break

  • 文本块升级 """ ,引入了文本块,可以使用 3 个双引号表示文本块,文本块内部不需要使用换行的转义字符

  • SocketAPI 重构,Socket 的底层实现优化,引入了 NIO

  • FileSystems.newFileSystem 新方法

  • ZGC 优化,增强 ZGC 释放未使用内存,将标记长时间空闲的堆内存空间返还给操作系统,保证堆大小不会小于配置的最小堆内存大小,如果堆最大和最小内存大小设置一样,则不会释放内存还给操作系统

重要特性:ZGC 优化,释放内存还给操作系统、Socket 底层实现引入 NIO。

JDK 14 新特性(2020 年 3 月)

  • instanceof 模式匹配,instanceof 类型匹配语法简化,可以直接给对象赋值,如  if(obj instanceof String str),如果 obj 是字符串类型则直接赋值给了 str 变量

  • 引入 Record 类型,类似于 Lombok 的 @Data 注解,可以向 Lombok 一样自动生成构造器、equals、getter等方法

  • Switch 表达式-标准化

  • 改进 NullPointerExceptions 提示信息,打印具体哪个方法抛的空指针异常,避免同一行代码多个函数调用时无法判断具体是哪个函数抛异常的困扰,方便异常排查

  • 删除 CMS 垃圾回收器

JDK 15 新特性(2020 年 9 月)

  • EdDSA  数字签名算法

  • Sealed Classes(封闭类,预览),通过 sealed 关键字修饰抽象类限定只允许指定的子类才可以实现或继承抽象类,避免抽象类被滥用

  • Hidden Classes(隐藏类)

  • 移除 Nashorn JavaScript 引擎

  • 改进 java.net.DatagramSocket 和 java.net.MulticastSocket 底层实现

JDK 16 新特性(2021 年 3 月)

  • 允许在 JDK C ++源代码中使用 C ++ 14功能

  • ZGC 性能优化,去掉 ZGC 线程堆栈处理从安全点到并发阶段

  • 增加 Unix 域套接字通道

  • 弹性元空间能力

  • 提供用于打包独立 Java 应用程序的 jpackage 工具

JDK 16 相当于是将 JDK 14、JDK 15的一些特性进行了正式引入,如 instanceof 模式匹配(Pattern matching)、record 的引入等最终到 JDK 16 变成了 final 版本。

基于 Java 8、11、17

JDK 17 新特性(2021 年 9 月)(LTS版本)

  • Free Java License

  • JDK 17 将取代 JDK 11 成为下一个长期支持版本

  • Spring 6 和 Spring Boot 3需要 JDK17

  • 移除实验性的 AOT 和 JIT 编译器

  • 恢复始终执行严格模式 (Always-Strict) 的浮点定义

  • 正式引入密封类 sealed class,限制抽象类的实现

  • 统一日志异步刷新,先将日志写入缓存,然后再异步刷新

虽然 JDK 17 也是一个 LTS 版本,但是并没有像 JDK 8 和 JDK 11 一样引入比较突出的特性,主要是对前几个版本的整合和完善。

重要特性详解

Java 模块化

JPMS(Java Platform Module System)是 Java 9 发行版的核心亮点。它也被称为Jigshaw项目[1]。模块是新的结构,就像我们已经有包一样。使用新的模块化编程开发的应用程序可以看作是交互模块的集合,这些模块之间具有明确定义的边界和依赖关系。

JPMS 包括为编写模块化应用程序提供支持,以及将 JDK 源代码模块化。JDK 9 附带了大约 92 个模块(在 GA 版本中可以进行更改)。Java 9 Module System有一个 java.base 模块。它被称为基本模块。它是一个独立的模块,不依赖于任何其他模块。默认情况下,所有其他模块都依赖于 java.base。

在 Java 模块化编程中:

  • 一个模块通常只是一个 jar 文件,在根目录下有一个文件 module-info.class。

  • 要使用模块,请将 jar 文件包含到 modulepath 而不是 classpath。添加到类路径的模块化 jar 文件是普通的 jar 文件,module-info.class 文件将被忽略。

典型的module-info.java类如下所示:

module helloworld {         exports com.alibaba.eight; } module test {         requires helloworld; }

总结:模块化的目的,是让 JDK 的各个组件可以被分拆,复用和替换重写。比如对 Java 的 GUI 不满意,可以自己实现一个 GUI,对 Java 的语法不满意,可以把 Javac 替换成其他语言和其他语言的编译器,比如 kotlin 和 kotlinc 等,没有模块化,几乎很难实现,每次修改某个模块,总不能把整个 JDK 给重新编译一遍,再发布一个整个 SDK 吧,模块化可以帮助更有效的定制化和部署。

本地变量类型推断

在 Java 10 之前版本中,我们想定义局部变量时,需要在赋值的左侧提供显式类型,并在赋值的右边提供实现类型:

MyObject value = new MyObject();

在 Java 10 中,提供了本地变量类型推断的功能,可以通过 var 声明变量:

var value = new MyObject();

本地变量类型推断将引入 var 关键字,而不需要显式的规范变量的类型。

其实,所谓的本地变量类型推断,也是 Java 10 提供给开发者的语法糖。

虽然我们在代码中使用 var 进行了定义,但其实虚拟机不认识这个 var,在 Java 文件编译成 class 文件的过程中,会进行解糖,使用变量真正的类型来替代 var。

HTTP 客户端 API-响应式流实现的 HttpClient

Java 使用 HttpURLConnection 进行 HTTP 通信已经很长一段时间了。但随着时间的推移,要求变得越来越复杂,应用程序的要求也越来越高。在 Java 11 之前,开发人员不得不求助于功能丰富的库,如 Apache HttpComponents 或 OkHttp 等。

我们看到 Java 9 发布了包含一个 HttpClient 实现作为实验性功能。它随着时间的推移而发展,现在是 Java 11 的最终功能。现在 Java 应用程序可以进行 HTTP 通信,而无需任何外部依赖。

作为 JDK 11 中正式推出的新 HTTP 连接器,支持的功能还是比较新的,主要的特性有:

  • 完整支持 HTTP 2.0 或者 HTTP 1.1

  • 支持 HTTPS / TLS

  • 有简单的阻塞使用方法

  • 支持异步发送,异步时间通知

  • 支持 WebSocket

  • 支持响应式流

HTTP 2.0其他的客户端也能支持,而 HttpClient 使用 CompletableFuture 作为异步的返回数据。WebSocket 的支持则是 HttpClient 的优势。响应式流的支持是 HttpClient 的一大优势。

HttpClient 中的 NIO 模型、函数式编程、CompletableFuture 异步回调、响应式流让HttpClient 拥有极强的并发处理能力,所以其性能极高,而内存占用则更少。

语法糖

Stream API 改进

Collectors.teeing()

teeing 收集器已公开为静态方法 Collectors::teeing。该收集器将其输入转发给其他两个收集器,然后将它们的结果使用函数合并。

示例:

List<Student> list = Arrays.asList(        new Student("唐一", 55),        new Student("唐二", 60),        new Student("唐三", 90));//平均分 总分String result = list.stream().collect(Collectors.teeing(        Collectors.averagingInt(Student::getScore),        Collectors.summingInt(Student::getScore),        (s1, s2) -> s1 + ":" + s2));//最低分  最高分String result2 = list.stream().collect(Collectors.teeing(        Collectors.minBy(Comparator.comparing(Student::getScore)),        Collectors.maxBy(Comparator.comparing(Student::getScore)),        (s1, s2) -> s1.orElseThrow() + ":" + s2.orElseThrow()));System.out.println(result);System.out.println(result2);
添加 Stream.toList 方法(JDK 16)
List<String> list = Arrays.asList("1", "2", "3");//之前这样写List<Integer> oneList = list.stream()    .map(Integer::parseInt)    .collect(Collectors.toList());//现在可以这样写List<Integer> twoList = list.stream()    .map(Integer::parseInt)    .toList();

Switch表达式改进

支持箭头表达式(JDK 12 预览 JDK 14 标准)

此更改扩展了 switch 语句以便它可以用作语句或表达式。不必为 break 的每个 case 块定义一个语句,我们可以简单地使用箭头语法。

boolean isWeekend = switch (day) {  case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> false;   case SATURDAY, SUNDAY -> true;  default -> throw new IllegalStateException("Illegal day entry :: " + day);};int size = 3;String cn = switch (size) {    case 1 -> "壹";    case 2 -> "贰";    case 3, 4 -> "叁";    default -> "未知";};System.out.println(cn);//要使用此预览功能,我们必须在应用程序启动期间使用–enable-preview标志明确指示 JVM。

基于 Java 8、11、17

yield 关键字(JDK 13)

使用 yield,可以有效地从 switch 表达式返回值,并能够更容易实现策略模式。

public class SwitchTest {public static void main(String[] args) {var me = 4;var operation = "平方";var result = switch (operation) {case "加倍" -> {yield me * 2;}case "平方" -> {yield me * me;}default -> me;};System.out.println(result);}
}

字符串

文本块改进(JDK 13)

早些时候,为了在我们的代码中嵌入 JSON,我们将其声明为字符串文字:

String json  = "{\r\n" + "\"name\" : \"lingli\",\r\n" + "\"website\" : \"https://www.alibaba.com/\"\r\n" + "}";

现在让我们使用字符串文本块编写相同的 JSON :

String json = """
{     "name" : "Baeldung",     "website" : "https://www.alibaba.com/"
}
""";

很明显,不需要转义双引号或添加回车。通过使用文本块,嵌入的 JSON 更易于编写,更易于阅读和维护。

更多的API
  • isBlank():如果字符串为空或字符串仅包含空格(包括制表符),则返回 true。注意与 isEmpty() 不同,isEmpty() 仅在长度为 0 时返回 true

  • lines():将字符串拆分为字符串流,每个字符串包含一行

  • strip() :分别从开头和结尾

  • stripLeading()/stripTrailing() 仅开始和仅结束删除空格

  • repeat(int times):返回一个字符串,该字符串采用原始字符串并按指定的次数重复该字符串

  • readString():允许从文件路径直接读取到字符串

  • writeString(Path path):将字符串直接写入指定路径处的文件

  • indent(int level):缩进字符串的指定量。负值只会影响前导空格

  • transform(Function f):将给定的 lambda 应用于字符串

instanceof 的模式匹配(JDK 14出预览,JDK 16最终确认)

之前:Object obj = "大阳";
if (obj instanceof String) {String t = (String) obj;// TODO
}现在:Object obj = "大阳";
if (obj instanceof String t) {// TODO 此时t已经是String类型了
}

record 记录类(JDK 16 正式)

传统的 Java 应用程序通过创建一个类,通过该类的构造方法实例化类,并通过 getter 和 setter 方法访问成员变量或者设置成员变量的值。有了 record 关键字,你的代码会变得更加简洁。

/*** record 记录类* 你也可以覆写equals() hashCode() toString()方法,不用写get、set了* @author DAYANG*/
record User(String name, Integer age) {@Overridepublic String toString() {return "User[" +"name='" + name + '\'' +", age=" + age +']';}@Overridepublic boolean equals(Object obj) {return false;}@Overridepublic int hashCode() {return 0;}
}

JVM

GC变化

JDK 9:设置 G1 为 JVM 默认垃圾收集器

JDK 10:并行全垃圾回收器 G1,通过并行 Full GC 改善 G1 的延迟。目前对 G1 的 full GC 的实现采用了单线程-清除-压缩算法。JDK 10 开始使用并行化-清除-压缩算法。

JDK 11:推出 ZGC 新一代垃圾回收器(实验性),目标是GC暂停时间不会超过 10 毫秒,既能处理几百兆的小堆,也能处理几个 T 的大堆。

JDK 14 :删除 CMS 垃圾回收器;弃用 ParallelScavenge + SerialOld GC 的垃圾回收算法组合;将 ZGC 垃圾回收器移植到 macOS 和 Windows 平台

JDk 15 : ZGC(JEP 377)和 Shenandoah(JEP 379)不再是实验性功能。默认的  GC 仍然是 G1

JDK 16:增强 ZGC,ZGC 获得了 46 个增强功能和 25 个错误修复,控制 stw 时间不超过 10 毫秒

指标测试

吞吐量比较

在吞吐量方面,Parallel 中 JDK 8 和 JDK 11 差距不大,JDK 17 相较 JDK 8 提升 15% 左右;G1 中 JDK 17 比 JDK 8 提升 18%;ZGC 在 JDK 11[2]引入,JDK 17 对比 JDK 11 提升超过 20%。

延迟比较

在 GC 延迟方面,JDK 17 的提升更为明显。我们可以看到为缩短 GC 暂停时间所做的努力都得到了回报,很多提升都是因为 GC 的改进。

在 Parallel 中 JDK 17 对比 JDK 8 和JDK 11 提升 40%;在 G1 中,JDK 11 对比 JDK 8 提升 26%,JDK 17 对比 JDK 8 提升接近 60%!ZGC 中 JDK 17 对比 JDK 11 提升超过 40%。

暂停时间对比

我们可以看到 JDK 17 中的 ZGC 远低于目标:亚毫秒级的暂停时间。G1 的目标是在延迟和吞吐量之间保持平衡,远低于其默认的目标:200 毫秒的暂停时间。ZGC 的设计会保证暂停时间不随堆的大小而改变,我们可以清楚地看到当堆扩大到 128 GB 时的情况。从暂停时间的角度来看,G1 比 Parallel 更善于处理更大的堆,因为它能够保证暂停时间满足特定目标。

资源占用

上图比较了三个不同收集器原生内存的使用峰值。由于从这个角度来看 Parallel 和 ZGC 都非常稳定,因此我们应该看一看原始数字。我们可以看到 G1 在这方面确实有所改进,主要原因是所有功能和增强功能都提高了记忆集管理的效率 。

总结:无论使用哪种收集器,与旧版本相比,JDK 17 [3] 的整体性能都有很大的提升。在 JDK 8 中,Parallel 是默认设置,但在 JDK 9 中改为了 G1。从那以后,G1 的改进速度就超过了 Parallel,但在有些情况下可能 Parallel 仍然是最佳选择。而 ZGC(JDK 15 正式使用)的加入,成为了第三种高性能替代方案。

其他

密封类和接口(15 预览 17 正式)

在 Java 15 之前,所有的类都可以没有限制地继承其他类--除非被继承类被声明为 final 类型,任何类都可以实现公共接口。

现在在 Java 15 中,一个类或者接口可以使用修饰符 sealed 声明为密封类或者接口,来限制其继承类。

/*** 定义一个抽象密封类Pet,它的实现类只能是Dog, Cat这两个,其他的实现类均不允许*/
public abstract sealed class Petpermits Dog, Cat {}final class Dog extends Pet {
}final class Cat extends Pet {}//密封的类和接口限制了其他类或接口可以扩展或实现它们
public sealed interface Shape{final class Planet implements Shape {}final class Star   implements Shape {}final class Comet  implements Shape {}
}public abstract sealed class Test{final class A extends Test {}final class B extends Test {}final class C extends Test {}
}

EdDSA 算法

EdDSA (Edwards-Curve Digital Signature Algorithm) 是在 Java 15 中通过 JEP 339添加的另一种附加数字签名方案。与其他可用的签名方案相比,它提供了更好的性能和安全的签名。

总结和展望

总结

1.Spring 带头猛冲,直接上 JDK 17。如果 Spring 6 还支持 Java 8 的话,那很多技术框架都要跟着 Java 8 的兼容,与其这样不如由 Spring 带头,一起飞升 Java 17,不过有些框架还不支持 JDK 17。

2.性能升级,光从 Java 8 换到 Java 11,啥也没干性能直接就提升了 10%(NIO 底层的重写),更何况一路到 JDK 17 过程中的 JVM 相关优化。不过光是性能的优化还不足以吸引企业进行JDK升级,毕竟加机器就能解决,费不着各种升级改造,还可能有安全问题。

3.JDK 21 可能成为真正的经典版本。目前还没有 Project loom 功能,代表着没有协程,性能方面比有协程 JDK 差远了。比如阿里开源的 JDK 8、11 就有非侵入式协程。

从发展趋势看,Project loom 功能在 JDK 19 已经可预览了,可以发现该版本许多的Java 工具都开始针对 loom 进行升级,Project loom 大概在 JDK 21 时正式推出,而JDK21 又是一个 LTS 版本 ,值得期待。

各种 servlet 容器,还有 jetty,netty,vert.x 等,在它们最新版本的 release note 找到对应的升级标注,说:我们添加了某某支持,其中最重要的就是 loom,或者叫作虚拟线程的支持, 可以预见一旦 JDK 21 发行,很多软件都会跟上投入生产!

Project loom 参考:https://open.atatech.org/articles/249741

基于 Java 8、11、17

展望

JDK的升级是必然趋势。

不升级的人说,目前来说国内很多程序猿可能觉得升级会造成额外工作,出了问题费力不讨好,要是出了安全问题,更是头疼。也有说没有实质性的好处,而且还有风险,还有从企业角度说,未来也不升级,因为去 Oracle 化。但考虑到未来 Oracle 不再维护JDK8,Spring 也不再维护过去版本的时候,为了跟上时代,使用最新技术,必然会助推 JDK 的升级。

当越来越多的公司加入 JDK 17 以上的大军中,未来更多的框架新版本都会最低支持JDK 17,因为兼容旧 JDK 实在不值得,当大部分框架和社区、论坛都是讨论 JDK17 的技术和各种解决问题的方法时,必然会反推企业进行升级。

经典好书推荐

说到学习 Java,那好书可真不少,甚至有人说不需要看书,直接看视频就能学会。但是随着项目的复杂,拿来即用的知识无法满足你的需求时,一本好书就起到至关重要的作用。

《On Java中文版》就是这样一套为你解惑的书。甚至是读源码、查文档也了解不到的 Java 开发细节,它都有讲。目前这本书的原版豆瓣评分 9.32,得到读者的高度关注。

那么,这本书究竟是怎样的一本书呢?

借用本书译者陈德伟老师的话来讲:

想要学习 Java 的开发者来说,立足于 Java 8,覆盖 Java 17,是最好的选择,而 On Java 中文版的出现恰逢其时

本书不仅介绍了 Java 的基础知识,还对 Java 8 和 Java 17 的内容作了重点讲解。作者借由函数式编程的视角,详细阐述了不同编程范式要应对的问题,并用单独的章节深入介绍了 Lambda 表达式、函数式接口和流。

《On Java中文版》一经上市,就成为江南白衣、杨晓峰、李三红等众多圈内大佬的强推书目。也是很多Java初学者、高级工程师、技术专家的必读书单。

较比同类书,这套书的价值在哪里?

  • 紧跟前沿,内容稀缺。如今,整个Java生态都在拥抱Java 17,但大部分书籍仍停留在Java 8,ON JAVA 涵盖了很多Java 8之后前言稀缺内容,比如隐藏类、模块化、密封类等特性。

  • 内容全面,深入浅出。对于Java的入门基础知识、日常工作使用的高级特性都有所兼顾,所以即使你是一名Java新手,也是容易上手阅读和学习的。

  • 注重实践,更易理解。本书最大的特色是与工程实践结合紧密,囊括了日常工作中遇到的各种开发难题,容易让你代入工作场景去思考这些技术对自身工作的帮助和改进。

不过,对新手来说,最关心的可能是“如何读?”的问题。我们特邀《解构领域驱动设计》的作者张逸、《高可用可伸缩微服务架构》的作者梁桂钊等知名专家为新手规划了一条阅读路线(“划重点”——见随书导读指南),并录制了配套的精讲视频,有效降低了新手的阅读门槛。

对视频感兴趣的朋友,可以去B站自取:https://www.bilibili.com/video/BV1Du411y7bf

从“面向对象编程”到“炼铁匠”

相信看过《Java编程思想》原版书的读者,应该对它的封面印象深刻,封面是由一个个封装着不同昆虫(bug)的木盒组成,同时也侧面盛赞了Java这门语言的安全性。

较比前者,《ON JAVA》封面发生了很大的变化,这幅封面的灵感来自于美国公共事业振兴署(Works Progress Administration,简称WPA),是1935—1943年美国大萧条时期所创建的一个大型公共事业项目,其目标是援助失业人口重新返回工作岗位。作者意在倡导“工匠精神”,真正的“代码匠”是需要在大量的实践和博识中逐渐才能形成自己的代码品味。

这很有意义,从编程本身到人的转变过程。

当然,好的“寓意”需要更好的装帧工艺来支撑,书的呈现效果上自然不能打折扣。全书采用锁线软精装工艺,比一般的平装书,更易翻阅,内文版式也做了特别的设计。

用“开放出版”的模式打磨译稿

引进出版外版技术书,经常被诟病的一点就是翻译质量,相信这也是所有读者最关心的点,这同样也是我们最重视的问题。

在招募译者之前,我们给本书译者定了一个很清晰的画像,需要具备 15 年以上 Java 从业经验,有长期阅读英文著作的习惯,中文功底扎实,语言表达流畅。基于此,我们前后共收到 200 篇试译稿,最终在经过层层筛选下,确定了 4 位译者来参与本书翻译。

同时,为了进一步保证翻译质量,我们邀请了来自行业内容的 20位一线 Java 专家和30位读者参与本书的审校工作,精准还原原作神韵。

京东目前5折,单册到手64.9。刚入门Java的新手,建议先看"基础卷",夯实基础。

进阶卷适合从业Java相关工作3~4年以上的朋友,即使是多年的老手,偶尔翻翻,也或有增益。业务中遇到各种棘手问题,基本都能从这本书找到“答案”。

ON JAVA为什么值得读,也可以听听他们的建议:

码农翻身:作为一本书,我是如何把别的Java系列卷死的!

架构师之路:为什么要读ON JAVA ?

程序猿DD: 都2022了,Java8之后的东西都应该学起来

技术琐话:40岁,编码的初心被唤醒

程序员cxuan:《On Java》值得读吗?

帅地玩编程:Java编程思想的重塑

点击【阅读原文】直达《On Java》B站讲解

一文详解|从 JDK 8 飞升到 JDK 17,再到未来的 JDK 21相关推荐

  1. 一文详解私募基金投资策略(8大类17小类)

    私募策略架构图 股票策略 股票策略是以投资股票类资产为主要收益来源,其投资标的为沪深上市公司股票,以及和股票相关的金融衍生工具(股指期货.ETF期权等).股票策略是目前国内阳光私募行业最主流的投资策略 ...

  2. 一文详解JavaBean 看这篇就够了

    一文详解JavaBean 看这篇就够了 JavaBean的历史渊源 JavaBean的定义(通俗版) JavaBean应用 < jsp:useBean > < jsp:getProp ...

  3. 【卷积神经网络结构专题】一文详解AlexNet(附代码实现)

    关注上方"深度学习技术前沿",选择"星标公众号", 资源干货,第一时间送达! [导读]本文是卷积神经网络结构系列专题第二篇文章,前面我们已经介绍了第一个真正意义 ...

  4. 一文详解 YOLO 2 与 YOLO 9000 目标检测系统

    一文详解 YOLO 2 与 YOLO 9000 目标检测系统 from 雷锋网 雷锋网 AI 科技评论按:YOLO 是 Joseph Redmon 和 Ali Farhadi 等人于 2015 年提出 ...

  5. 一文详解决策树算法模型

    AI有道 一个有情怀的公众号 上文我们主要介绍了Adaptive Boosting.AdaBoost演算法通过调整每笔资料的权重,得到不同的hypotheses,然后将不同的hypothesis乘以不 ...

  6. 「软件项目管理」一文详解软件配置管理计划

    一文详解软件配置管理计划 前言 一.配置管理概述 1. 配置管理(SCM)定义 2. 软件配置项目(SCI) 3. 基线 4. 软件配置控制委员会(SCCB) 二.软件配置管理过程 1. 管理过程 2 ...

  7. 「软件项目管理」一文详解软件项目质量计划

    一文详解软件项目质量计划

  8. 「软件项目管理」一文详解软件项目管理概述

    一文详解软件项目管理概述

  9. OpenCV-Python实战(12)——一文详解AR增强现实

    OpenCV-Python实战(12)--一文详解AR增强现实 0. 前言 1. 增强现实简介 2. 基于无标记的增强现实 2.1 特征检测 2.2 特征匹配 2.3 利用特征匹配和单应性计算以查找对 ...

  10. Python-Matplotlib可视化(10)——一文详解3D统计图的绘制

    Python-Matplotlib可视化(10)--一文详解3D统计图的绘制 前言 3D散点图 3D曲线图 3D标量场 绘制3D曲面 在3D坐标轴中绘制2D图形 3D柱形图 系列链接 前言 Matpl ...

最新文章

  1. 左神讲算法——异或的高级操作(两数交换+经典面试题)
  2. ecshop的Mysql操作类
  3. 打造完全绿色的TOTAL COMMANDER
  4. nginx反向代理tomcat
  5. 19年计算机专硕学硕报名人数,2019年研招报考数据出炉!专硕的报考人数赶超学硕!...
  6. 用c#算成绩的总和_用c#输入几门课程成绩求总成绩和平均成绩,定义方法实现如果输入的成绩不是整数,则重新输入(方法)...
  7. 美国计算机科学奥林匹克竞赛试题,中学信息奥林匹克竞赛试题精选.doc
  8. poj 1905 Expanding Rods (数学 计算方法 二分)
  9. 【用python写一个简易的消息轰炸代码】
  10. Unity3d 联通沃商店接入问题
  11. 【CSDN竞赛第四期】编程赛后总结与分享
  12. 喜茶奶茶技术培训哪里学?
  13. 五金切断模具结构和设计注意事项
  14. 描述流体中声学物理现象的三个基本方程
  15. HTTP请求中的OPTIONS请求
  16. MTK Android software Tools工具的说明
  17. linux boot菜单列表,/boot/grub/menu.lst详解
  18. 戴尔服务器光盘装Linux系统,DELL服务器引导光盘下载连接,DELL引导盘万能驱动支持所有型号...
  19. 文字转语音朗读如何操作?手把手教你如何将文字转语音
  20. 软件自动更新解决方案及QT实现(源码已上传)

热门文章

  1. 获取用户的操作系统及浏览器信息
  2. python进阶练习题:括号是响亮!【难度:2级】--景越Python编程实例训练营,不同难度Python习题,适合自学Python的新手进阶
  3. for循环遍历集合取出其中某一项的值
  4. 记录自己的日常学习生活
  5. UC浏览器快开之路:如何应对大型APP优化工作周而复始难题?
  6. 【51nod 1028 大数乘法 V2】
  7. 需求工程之软件需求规格文档(SRS文档)
  8. 实现el-table树形表格所有行的展开与收起
  9. R语言dplyr包summarise_at函数计算dataframe数据中多个数据列(通过向量指定)的计数个数、均值和中位数、使用list函数指定函数列表并指定自定义函数名称
  10. 游侠汽车宣布B+轮融资3.5亿美金 估值33.5亿美金