Java 标准库

最后更新: 2021-06-11 09:05:39 +0800 +0800
原文以英文撰写。您正在阅读AI翻译版本。

小型库的契约往往比 API 的表面积更能决定正确性。以下规则可以避免常见的 Java 集成失败。

对象契约 #

equals 必须满足自反性、对称性、传递性和一致性,并且对null返回 false。 如果两个对象相等,它们必须具有相同的hashCode;因此,在将值用作哈希键之前, 应同时重写这两个方法。对象作为映射键期间,不要修改参与相等性判断的字段。 如果继承会破坏对称性,应优先使用组合而非继承。

Object.clone执行字段复制,并且与构造函数、继承和可变字段的配合较差。 应优先使用复制构造函数或命名为copyOf的工厂方法。数组是一个范围有限的例外, 因为它们的clone具有可预测的浅数组契约。

文本、正则表达式和字符串 #

对于会重复使用的Pattern,应进行编译。Matcher.matches()要求整个输入都匹配, 而find()搜索下一个匹配区域。Pattern.quote(value)会转义放入正则表达式的 字面文本;Matcher.quoteReplacement(value)会转义替换字符串。两者不能互换。

从 JDK 9 开始,HotSpot 的String实现使用紧凑字符串:通过byte[]加编码标记, 可以紧凑地表示 Latin-1 文本,否则使用 UTF-16。这属于实现细节;Java String 仍然是 UTF-16 代码单元序列,并且必须在 I/O 边界显式进行Charset转换。

计数器和枚举集合 #

AtomicLong提供一个精确且线性一致的值。LongAdder在存在竞争时将更新分散到 多个单元中,因此更新具有更好的扩展性,但与更新并发执行的sum()不是原子快照。 对于度量指标使用LongAdder;当每个观测到的总数都会驱动正确性判断时,使用 AtomicLong。

Enum<E extends Enum<E>>为单个枚举类型提供类型安全的排序和操作。EnumSet和 EnumMap利用这一封闭的键空间,并保留枚举声明顺序;对于枚举域,应优先使用 它们而不是HashSet和HashMap。

集合和线程 #

Thread.State报告BLOCKED、WAITING和TIMED_WAITING等 JVM 级别的状态; 它用于观察,而不是同步协议。应使用join、future、闩锁或结构化所有权来协调线程。

Map是否允许null键或值取决于具体实现:HashMap允许一个 null 键,而 ConcurrentHashMap拒绝 null 键和值;在自然排序下,TreeMap也可能拒绝 null 键。不要假定Map接口的可选操作一定成功,而应验证所选实现的契约。

Arrays.asList(array)返回一个由所提供对象数组支持的固定大小列表。set会更新 该数组,但add和remove会失败。传入int[]会创建包含一个元素的List<int[]>, 因为可变参数不会将基本类型数组装箱。需要装箱值列表时,请使用 Arrays.stream(ints).boxed().toList()。

参考资料 #

评论

在 GitHub 上阅读或评论(发表评论需要登录)