第1章 导言
把90条建议视为带前提和取舍的工程判断,而不是脱离情境的Java戒律。覆盖1个正式目录节点,并通过决策图、取舍实验和反例证据复核。
为什么“第1章 导言”必须从情境与取舍开始
把90条建议视为带前提和取舍的工程判断,而不是脱离情境的Java戒律。本页属于正式单元,目标不是复制原书短文,而是依照 InformIT/Addison-Wesley 官方第3版详细目录,把每个Item重构成情境、备选方案、最小反例、验证和决议。正式节点共1个,最终产物是Item决策记录模板、Java 9基线与Java 25复核清单。
Effective Java给的是工程建议,不是语言规范。建议通常优化长期API、类型安全、可维护性或正确性,但可能增加对象、样板、迁移或运行成本。高质量应用必须先声明调用者、API寿命、威胁模型和性能预算,再解释为什么本Item在这个情境中优于替代方案。
版次坐标与现代边界
本课程采用 Joshua Bloch 的 Effective Java, Third Edition,Addison-Wesley Professional,2017年12月出版,版权2018,416页,ISBN 9780134685991。官方详细目录确认12章、90条Item,另有第二版条目对照、参考文献与索引;课程覆盖15个正式单元、105个目录节点,另设学习地图和综合验收,共17页。
原书覆盖至Java 9。课程保持Item原义和编号,同时把Java 25作为复核边界:record、sealed class、模式匹配、虚拟线程、FFM等可能改变实现手段,但不会自动证明原建议失效。任何现代补充都要标注“原书建议”“后续语言/API变化”和“本项目决策”三层,避免伪装成原文。
五个贯穿全书的术语
、、、、。
适用前提限定建议范围,备选方案防止二元思维,边界反例测试结论,兼容触点量化演化成本,决策记录让未来维护者能重放推理。
四个可复算指标
Item覆盖检查90条建议是否都有决策落点:
反例覆盖同时考虑正常、边界、失败和替代方案:
API兼容触点可粗略表示为公开表面积与调用方乘积:
决策风险由影响面、未验证比例与可变共享状态放大:
这些数值用于定位缺口,不证明设计优越。Item覆盖100%可能只是机械同意;兼容触点少也可能来自功能不足。必须同时保存反例、被放弃方案和质性理由。
Chapter 1: Introduction
正式节点 1/1。 先声明调用方、API寿命、Java版本、性能/安全约束和允许破坏范围,再判断该建议是否适用。 “Chapter 1: Introduction”必须服务于“把90条建议视为带前提和取舍的工程判断,而不是脱离情境的Java戒律”,并在“Item决策记录模板、Java 9基线与Java 25复核清单”中留下决策和证据。
至少执行原方案、采用建议、边界反例三组对照,说明收益由谁获得、成本由谁承担、Java 9到Java 25是否改变前提。若出现“只背结论,不记录适用前提、替代方案、代价和推翻结论的反例”,就调整适用域或拒绝建议,不能把Item编号当作论证本身。
把90条建议读成一套约束系统
第三版不是90条互不相干的技巧清单。第2章先约束对象怎样出生、共享和退出,第3章规定对象进入集合与诊断工具时必须满足的值语义,第4至8章逐步收紧类型、抽象边界与API形状,第9至12章再处理实现细节、失败路径、并发与跨进程表示。阅读时应为每条Item标记“它保护哪一方”:调用者、实现者、子类型作者、并发参与者,还是长期保存的数据。若不知道保护对象,就无法判断建议带来的封装成本是否值得。
建议之间还存在优先级。安全性、正确性和可恢复性通常高于局部简洁;公开合同的兼容性高于一次实现便利;经过测量的性能事实高于对分配或锁的直觉。例如静态工厂可以改善命名与缓存,但若框架必须反射调用公开构造器,就要记录例外。组合优于继承可以隔离脆弱基类,但若领域合同确实要求可替换子类型,则需先证明Liskov条件,而不是机械禁用继承。
为避免“现代Java已经替我解决”的误判,每次现代化都做两栏记录。左栏保持Java 9原书问题:可变状态、类型擦除、异常合同、序列化攻击面和线程协调。右栏记录Java 25可用工具:record、sealed class、模式匹配、模块边界、虚拟线程等。工具只能降低实现成本,不能自动消除原问题;record仍可持有可变组件,sealed层次仍要维护值合同,虚拟线程仍会共享内存。
一条Item只有经过四个出口才算掌握:能用自己的话说明问题,能写出违反建议的最小客户端,能指出至少一个不适用情境,能给出可重复的验证。代码评审中使用“情境 -> 风险 -> 备选 -> 证据 -> 决策 -> 回滚”顺序,禁止只写“依据Item 17”。最后把多个Item放入同一变更重放,检查局部改进是否把成本转移到序列化格式、调用方兼容或并发调度上。
导言验收清单
- 从真实公共API选择一个决策,明确寿命、调用方数量和允许破坏范围。
- 关联至少两条可能冲突的Item,并说明裁决优先级。
- 在Java 9与当前JDK各运行一次客户端、反例和失败路径。
- 保存基线、测量结果、未采用方案和触发回滚的阈值。
- 让未参与实现的评审者只凭记录复现结论;不能复现就补证据。
最终交付不是“读完90条”的勾选表,而是一组可追溯决策。每张记录要能回答:若调用方增加、JDK升级、性能目标变化或出现新攻击面,哪条前提会先失效,谁负责重新验证,怎样在不破坏公共合同的情况下回退。随机抽取三张记录,若评审者能从反例推回风险、从风险找到Item、再从Item重放测试,才说明阅读形成了工程能力。
记录还应保存决策日期、目标JDK、公开API快照、测试入口和负责人。半年后用同一客户端重放一次,若结果变化,要区分环境漂移、实现优化和合同变化,并把结论更新传播到依赖它的代码规范与评审模板。
建立Item决策档案
每条Item建立一张记录:问题情境、调用方、原方案、建议方案、替代方案、收益、代价、最小反例、验证类型、Java版本和回滚条件。若多个Item同时作用,例如“不可变性”与“构建器”、“接口”与“反射”、“失败原子性”与“防御复制”,要画出依赖和冲突,按全局API合同裁决。
还要做版本三角复核。第一角是Java 9原书语境,第二角是Java 25语言/API能力,第三角是当前项目约束。新特性可能降低建议成本,例如record帮助不可变值;也可能引入新边界,例如虚拟线程不会消除共享状态竞态。只有三角中的差异被测试,才能决定“原样采用、现代化实现、缩小适用域或拒绝”。
本单元的最小示例是独立教学重构:
record ItemDecision(int item, String context, String choice, String counterexample) {}
var decision = new ItemDecision(1, "public API", "static factory", "subclass construction required");
System.out.println(decision);客户端测试要在公共边界验证行为,而不是复制实现:
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
class ItemDecisionTest {
@Test void alternativeBoundaryAndRollbackStayVisible() {
var evidence = java.util.List.of("baseline", "item", "counterexample", "rollback");
assertAll(
() -> assertEquals(4, evidence.size()),
() -> assertTrue(evidence.contains("counterexample")),
() -> assertTrue(evidence.indexOf("baseline") < evidence.indexOf("item"))
);
}
}交接标准要求另一位评审者重放决策:
Feature: Chapter 1: Introduction
Scenario: reproduce an Item decision
Given the Java version, caller contract, and original alternative
When a reviewer runs the baseline, recommended design, and counterexample
Then benefits, costs, compatibility impact, and failure semantics are visible
And the reviewer can keep, narrow, or reject the advice with evidence先预测再运行
先预测:公开成员从12增至30、可变状态从35%增至80%、调用方从8增至24时,兼容触点、状态风险、测试下界和演化成本怎样变化?一次只改变一个变量,观察编译客户端数、突变失败、并发交错、分配与P95延迟。数据偏离预测时,先检查调用方假设、Item冲突、实现偶然和Java版本变化。
三类高频误区
本章回顾
“第1章 导言”的核心是把“把90条建议视为带前提和取舍的工程判断,而不是脱离情境的Java戒律”转成可复核工程决策。完整链路包含适用前提、备选方案、Item原义、现代版本差异、边界反例、可编译客户端、度量与回滚;缺少任一环,都只是对建议的表态,而非设计证据。