关于我们
![]() ![]() |
Java程序员修炼之道(第2版) 读者对象:本书适用于JAVA语言程序设计相关专业师生及从业者 ![]()
《Java 程序员修炼之道(第2 版)》是为有志成为卓越 Java 开发者的人编写的实用指南。相比于第 1 版,第 2 版扩展了内容,深入探讨了 Java 8、11 及更高版本的特性。本书不仅覆盖了 Java 语言本身的新特性,还引入了与现代开发实践息息相关的主题,包括函数式编程、并发、多语言编程及容器化部署等。本书的核心目标是帮助开发者建立扎实的基础,掌握 Java 语言和 JVM 平台的深层知识,同时引导读者了解 Java 生态中的非 Java 语言,如 Kotlin 和 Clojure。通过对 Java 语言核心原理的学习,读者将掌握如何高效地使用 Java,如何应对日益复杂的开发环境,并理解平台的未来演化方向。
Java 是企业级开发的核心引擎,真正精通 Java 的程序员,永远不愁好工作,更能参与有趣的项目!本书由Java Champions 和资深架构师联手打造,凝结数十年 Java 实战经验,让你少走弯路,掌握真正能在工作中派上用场的核心技能!
通过本书,你将突破 API 级别的学习,直击字节码、性能调优、高并发优化等高价值技术,并精通 Maven、Gradle 在 CI/CD 流程中的应用,同时还能掌握 Kotlin、Clojure 这些新潮的 JVM 语言到底怎么和 Java 无缝协作。
本杰明·J. 埃文斯(Benjamin J. Evans)
全球 Java 领域最具影响力的技术专家之一。作为 Java Champion,他在 Java 社区享有崇高声誉,参与制定Java标准,直接影响 Java 生态的发展方向。目前担任红帽公司首席软件工程师,致力于企业级 Java 解决方案的创新与优化。
杰森·克拉克(Jason Clark)
New Relic 公司首席工程师和架构师,专注于高性能分布式系统、云计算和 Java 生态的优化。他在企业级软件开发、微服务架构和 JVM 深度优化方面有丰富的经验。
马丁·韦尔伯格(Martijn Verburg)
Java 生态领域的顶尖技术领袖之一,AdoptOpenJDK(现为 Eclipse Adoptium) 联合创始人,现任微软首席工程组经理(Java & Golang)。同时,马丁是伦敦 Java 社区(LJC)的联合领导者,致力于推动 Java 技术在全球开发者社区中的普及与创新。他在多个 Java 规范组织中担任重要角色,直接参与 Java 标准的制定与演进。
第 一部分 从 Java 8 到 Java 17 及更高版本
第 1章 现代 Java 介绍 2 1.1 Java 语言和 Java 平台 2 1.2 Java 的新发布模型 4 1.3 类型推断增强(var 关键字) 7 1.4 语言和平台的更改 10 1.4.1 撒点儿糖 11 1.4.2 语言更改 11 1.4.3 JSR 和 JEP 12 1.4.4 孵化特性和预览特性 12 1.5 Java 11 中的小变更 13 1.5.1 集合工厂(JEP 213) 13 1.5.2 移除企业版模块(JEP 320) 14 1.5.3 HTTP/2(Java 11) 15 1.5.4 单文件源代码程序(JEP 330) 19 小结 21 第 2章 Java 模块 22 2.1 场景设置 22 2.1.1 Jigsaw 项目 23 2.1.2 模块图 26 2.1.3 保护内部 27 2.1.4 新的访问控制语义 28 2.2 模块的基本语法 29 2.2.1 导出和依赖 30 2.2.2 传递性 31 2.3 模块加载 32 2.3.1 平台模块 32 2.3.2 应用模块 33 2.3.3 自动模块 33 2.3.4 未命名模块 34 2.4 构建模块化应用程序 34 2.4.1 模块的命令行开关 35 2.4.2 运行模块化应用 37 2.4.3 模块与反射 38 2.5 模块架构 39 2.5.1 拆分包 40 2.5.2 Java 8 运行时精简模式 40 2.5.3 多版本 JAR 42 2.6 超越模块 45 小结 46 第3章 Java 17 47 3.1 文本块 47 3.2 switch 表达式 48 3.3 record 51 3.3.1 名义类型 56 3.3.2 紧凑记录构造器 58 3.4 sealed 59 3.5 instanceof 的新用法 63 3.6 模式匹配和预览特性 65 小结 67 第二部分 内部原理 第4章 类文件和字节码 70 4.1 类加载和类对象 71 4.1.1 加载和链接 72 4.1.2 类对象 73 4.2 类加载器 74 4.2.1 自定义类加载器 76 4.2.2 模块和类加载 82 4.3 检查类文件 82 4.3.1 javap 简介 83 4.3.2 方法签名的内部表示形式 83 4.3.3 常量池 84 4.4 字节码 87 4.4.1 分解类文件 87 4.4.2 运行时环境 89 4.4.3 操作码介绍 91 4.4.4 加载和存储操作码 92 4.4.5 数学运算操作码 93 4.4.6 流程控制操作码 93 4.4.7 调用操作码 94 4.4.8 平台操作码 97 4.4.9 操作码的快捷形式 97 4.5 反射 98 4.5.1 反射概述 98 4.5.2 类加载与反射 100 4.5.3 反射的局限性 101 小结 102 第5章 Java 并发基础 103 5.1 并发理论 104 5.1.1 我已经了解线程了 104 5.1.2 硬件 104 5.1.3 Amdahl 定律 105 5.1.4 Java 的线程模型 106 5.1.5 经验教训 107 5.2 设计原则 107 5.2.1 安全性 107 5.2.2 活跃度 108 5.2.3 性能 109 5.2.4 重用性 109 5.2.5 这些设计原则为何以及如何 相互冲突 109 5.2.6 系统开销之源 110 5.3 块结构并发 110 5.3.1 同步与锁 111 5.3.2 线程的状态模型 112 5.3.3 完全同步对象 113 5.3.4 死锁 114 5.3.5 为什么要同步 117 5.3.6 volatile 关键字 118 5.3.7 Thread 类的状态和方法 119 5.3.8 不变性 124 5.4 Java 内存模型 128 5.5 通过字节码理解并发 129 5.5.1 更新丢失 131 5.5.2 同步的字节码表示 133 5.5.3 同步方法 136 5.5.4 非同步读取 137 5.5.5 重温死锁 139 5.5.6 重温死锁解决方案 141 5.5.7 易失性访问 145 小结 147 第6章 JDK 并发库 148 6.1 现代并发程序的构建块 148 6.2 原子类 149 6.3 锁 150 6.4 CountDownLatch 152 6.5 ConcurrentHashMap 154 6.5.1 简化版 HashMap 154 6.5.2 Dictionary 的局限性 157 6.5.3 并发 Dictionary 158 6.5.4 使用 ConcurrentHashMap 160 6.6 CopyOnWriteArrayList 162 6.7 阻塞队列 165 6.7.1 使用 BlockingQueue API 170 6.7.2 使用工作单元 171 6.8 Future 172 6.9 任务与执行 175 6.9.1 任务建模 176 6.9.2 执行器 177 6.9.3 单线程执行器 178 6.9.4 大小固定的线程池 178 6.9.5 缓存线程池 179 6.9.6 ScheduledThreadPool-Executor 180 小结 181 第7章 理解 Java 性能 182 7.1 性能术语:基本定义 184 7.1.1 时延 184 7.1.2 吞吐量 185 7.1.3 利用率 185 7.1.4 效率 185 7.1.5 容量 185 7.1.6 可扩展性 185 7.1.7 退化 185 7.2 性能分析的实用方法 186 7.2.1 知道自己在测量什么 186 7.2.2 了解如何进行测量 187 7.2.3 知道性能目标是什么 188 7.2.4 知道什么时候停止 188 7.2.5 了解实现更高性能的成本 189 7.2.6 了解过早优化的危险 189 7.3 出了什么问题,我们为什么要关心 190 7.3.1 摩尔定律 190 7.3.2 理解内存延迟层级 192 7.4 Java 性能调优为什么这么难 193 7.4.1 时间在性能调优中的作用 194 7.4.2 理解缓存未命中 195 7.5 垃圾收集 196 7.5.1 基础知识 197 7.5.2 标记-清除 197 7.5.3 内存区域 199 7.5.4 新生代垃圾收集 199 7.5.5 老年代垃圾收集 200 7.5.6 安全点 200 7.5.7 G1:Java 的默认垃圾收集器 200 7.5.8 并行收集器 202 7.5.9 GC 配置参数 203 7.6 使用 HotSpot 进行 JIT 编译 204 7.6.1 为什么要动态编译 205 7.6.2 HotSpot 简介 205 7.6.3 内联方法 206 7.6.4 动态编译和单态分派 207 7.6.5 理解编译日志 207 7.6.6 逆优化 208 7.7 JDK 飞行记录器 209 7.7.1 JFR 209 7.7.2 JMC 210 小结 215 第三部分 JVM 上的多语言编程 第8章 JVM 语言 218 8.1 语言生态学 218 8.1.1 解释型语言与编译型语言 219 8.1.2 动态类型语言与静态类型语言 219 8.1.3 命令式语言与函数式语言 220 8.1.4 对现有语言的重新实现与原始 JVM 语言 221 8.2 JVM 上的多语言编程 222 8.2.1 为什么使用非 Java 语言 223 8.2.2 新兴语言 225 8.2.3 那些我们没有选择的语言 226 8.3 如何为项目选择非 Java 语言 227 8.3.1 项目域的风险承受能力是高还是低 228 8.3.2 该语言与 Java 的互操作性如何 228 8.3.3 这门语言是否有良好的工具和测试支持 229 8.3.4 这门语言有多难学 229 8.3.5 使用这门语言的开发者多吗 229 8.4 JVM 对其他语言的支持 230 8.4.1 性能 230 8.4.2 非 Java 语言的运行时环境 231 8.4.3 编译器虚构 231 小结 233 第9章 Kotlin 234 9.1 为什么使用 Kotlin 234 9.2 便利和简洁 235 9.2.1 从少开始 235 9.2.2 变量 236 9.2.3 相等性 236 9.2.4 函数 237 9.2.5 集合 240 9.2.6 表达自己 242 9.3 对类和对象的不同看法 244 9.4 安全 250 9.4.1 空安全 250 9.4.2 智能转型 251 9.5 并发 253 9.6 与 Java 的互操作性 256 小结 259 第 10章 Clojure:编程新视角 260 10.1 介绍 Clojure 261 10.1.1 在 Clojure 中实现 Hello World 262 10.1.2 REPL 入门 264 10.1.3 犯错 265 10.1.4 学着去爱括号 268 10.2 寻找 Clojure:语法和语义 269 10.2.1 特殊形式训练营 269 10.2.2 列表、向量、映射和集合 271 10.2.3 算术、相等和其他操作 274 10.2.4 使用函数 275 10.2.5 Clojure 中的循环 278 10.2.6 读取器宏和派发器 279 10.3 函数式编程和闭包 281 10.4 Clojure 序列 282 10.5 Clojure 和 Java 的互操作 287 10.5.1 从 Clojure 中调用 Java 288 10.5.2 Clojure 调用的本质 288 10.5.3 Clojure 值的 Java 类型 289 10.5.4 使用 Clojure 代理 290 10.5.5 使用 REPL 进行探索式编程 290 10.5.6 在 Java 中使用 Clojure 291 10.6 宏 292 小结 296 第四部分 构建和运行 Java 应用 第 11章 构建工具 Gradle 和 Maven 298 11.1 为什么构建工具对优秀的程序员至关重要 298 11.1.1 自动化烦琐的操作 298 11.1.2 管理依赖 299 11.1.3 确保开发者间的一致性 302 11.2 Maven 303 11.2.1 构建生命周期 303 11.2.2 命令 /POM 概述 304 11.2.3 构建 305 11.2.4 控制清单文件 306 11.2.5 添加多语言支持 307 11.2.6 测试 310 11.2.7 依赖管理 313 11.2.8 评估 316 11.2.9 超越 Java 8 317 11.2.10 如何在 Maven 中使用不同版本的 JAR 318 11.2.11 Maven 与模块 321 11.2.12 编写 Maven 插件 324 11.3 Gradle 327 11.3.1 安装 Gradle 327 11.3.2 任务 328 11.3.3 脚本 329 11.3.4 使用插件 330 11.3.5 构建 331 11.3.6 避免工作 333 11.3.7 Gradle 中的依赖 334 11.3.8 增加对 Kotlin 的支持 338 11.3.9 测试 339 11.3.10 自动化静态分析 340 11.3.11 超越 Java 8 341 11.3.12 通过 Gradle 使用模块 341 11.3.13 定制化 347 小结 350 第 12章 在容器中运行 Java 351 12.1 为什么容器对优秀的 Java 程序员至关重要 351 12.1.1 操作系统、虚拟机、容器的区别与联系 351 12.1.2 容器的优势 353 12.1.3 容器的缺点 354 12.2 容器基础 355 12.2.1 构建容器镜像 355 12.2.2 运行 Docker 容器 358 12.3 使用 Docker 开发 Java 应用程序 360 12.3.1 选择基础镜像 360 12.3.2 使用 Gradle 构建镜像 361 12.3.3 在容器中执行构建 362 12.3.4 端口与主机 364 12.3.5 使用 Docker Compose 进行本地开发 366 12.3.6 在容器中调试 369 12.3.7 容器中的日志 371 12.4 Kubernetes 372 12.5 可观测性与性能 379 12.5.1 可观测性 379 12.5.2 容器中的性能 381 小结 382 第 13章 测试基础 383 13.1 为什么要测试 383 13.2 如何开展测试 384 13.3 测试驱动开发 386 13.3.1 TDD 概述 387 13.3.2 一个单一用例的 TDD 示例 388 13.4 测试替身 393 13.4.1 Dummy 对象 394 13.4.2 Stub 对象 396 13.4.3 Fake 对象 398 13.4.4 Mock 对象 400 13.4.5 Mock 的问题 401 13.5 从 JUnit 4 到 JUnit 5 402 小结 408 第 14章 测试不止 JUnit 409 14.1 使用 Testcontainers 进行集成测试 409 14.1.1 安装 testcontainers 库 409 14.1.2 Redis 示例 410 14.1.3 收集容器的日志 413 14.1.4 Postgres 示例 414 14.1.5 使用 Selenium 进行端到端测试的示例 416 14.2 利用 Spek 和 Kotlin 规范测试风格 418 14.3 使用 Clojure 进行基于属性的测试 423 14.3.1 clojure.test 423 14.3.2 closure.spec 425 14.3.3 test.check 428 14.3.4 clojure.spec 和test.check 433 小结 434 第五部分 Java世界的前沿展望 第 15章 高级函数式编程 436 15.1 函数式编程的概念 436 15.1.1 纯函数 437 15.1.2 不可变性 437 15.1.3 高阶函数 437 15.1.4 递归 438 15.1.5 闭包 438 15.1.6 惰性求值 439 15.1.7 柯里化与部分执行 439 15.2 Java 作为一门函数式语言的局限性 440 15.2.1 纯函数 440 15.2.2 可变性 441 15.2.3 高阶函数 443 15.2.4 递归 444 15.2.5 闭包 447 15.2.6 惰性求值 448 15.2.7 柯里化与部分执行 450 15.2.8 Java 的类型系统与集合类型 450 15.3 Kotlin 中的函数式编程 452 15.3.1 纯函数及高阶函数 452 15.3.2 闭包 453 15.3.3 柯里化与部分执行 454 15.3.4 不可变性 455 15.3.5 尾递归 458 15.3.6 惰性求值 461 15.3.7 序列 462 15.4 Clojure 的函数式编程 466 15.4.1 推导式 466 15.4.2 惰性序列 467 15.4.3 Clojure 中的柯里化 469 小结 470 第 16章 高级并发程序设计 471 16.1 Fork/Join 框架 471 16.1.1 一个简单的 Fork/Join应用示例 472 16.1.2 通过 Fork/Join 框架将问题处理并行化 475 16.1.3 工作窃取算法 476 16.2 并发与函数式编程 477 16.2.1 回顾 CompletableFuture 477 16.2.2 并行流 481 16.3 深入了解 Kotlin 协程的实现原理 482 16.3.1 协程的工作原理 482 16.3.2 协程的作用域及调度 487 16.4 Clojure 中的并发实践 489 16.4.1 持久化数据结构 490 16.4.2 Future 和 pcall 495 16.4.3 软件事务内存 497 16.4.4 代理 500 小结 501 第 17章 现代内核 503 17.1 JVM 内核概述 503 17.1.1 调用虚方法 504 17.1.2 调用接口方法 507 17.1.3 调用“特殊”方法 508 17.1.4 final 方法 509 17.2 反射的内部机制 510 17.3 方法句柄 514 17.3.1 MethodHandle 514 17.3.2 MethodType 516 17.3.3 查找方法句柄 516 17.3.4 反射、代理和方法句柄 517 17.4 动态调用 519 17.5 JVM 内核的最新变化 523 17.5.1 字符串连接 523 17.5.2 压缩字符串 525 17.5.3 Nestmates 527 17.6 Unsafe 类 529 17.7 用支持的 API 替换 Unsafe 533 17.7.1 VarHandles 534 17.7.2 隐藏类 535 小结 537 第 18章 Java 的未来 538 18.1 项目 Amber 538 18.2 项目 Panama 540 18.3 项目 Loom 546 18.3.1 虚拟线程 549 18.3.2 线程构建器 550 18.3.3 使用虚拟线程编程 551 18.3.4 项目 Loom 什么时候发布 552 18.4 项目 Valhalla 553 18.4.1 改变语言模型 556 18.4.2 值对象带来的影响 557 18.4.3 回顾泛型 559 18.5 Java 18 559 小结 560 附录A 选择 Java 版本 561 附录B 回顾 Java 8 中的流 564
你还可能感兴趣
|