Files
global-coding-governance/java-coding-style/references/02-类型OOP与API设计.md
T

4.4 KiB
Raw Blame History

类型、OOP 与 API 设计

类型与相等性

  • 必须:包装类型使用 equalsObjects.equals 比较值,不使用 ==;警惕缓存范围造成的偶然相等。
  • 必须BigDecimal 使用字符串或精确来源构造;数值大小用 compareTo,需要比较值与 scale 时才用 equals
  • 必须:货币、比例和计量值明确精度、舍入方式与单位;禁止用 double 承载精确金额。
  • 必须:重写 equals 时同时重写 hashCode,并验证对称性、传递性和集合行为。
  • 推荐:用领域类型、枚举和受约束构造器替代多个语义不明的 Stringint 参数。
  • 必须:类型转换前检查范围和语义;不得以强制转换静默截断数值。

空值与返回值

  • 必须:明确参数与返回值的 nullability;不得依靠调用方猜测。
  • 推荐:返回空集合或空数组而非 null;不要为避免判断而创建语义虚假的空领域对象。
  • 推荐Optional 主要用于可能缺失的返回值;不要默认用于实体字段、DTO 字段、方法参数或集合元素。
  • 必须:禁止无条件链式解引用可能为空的对象;在边界校验或使用清晰分支表达缺失语义。
  • 必须:不要用断言校验外部输入,因为生产环境可能禁用断言。
  • 推荐:在系统边界尽早校验参数;项目支持 Bean Validation 时优先使用 @Valid@NotNull@NotBlank@Size 等声明式校验。
  • 推荐:内部前置条件优先复用项目已有校验工具;只有需要定制业务错误码或分支处理时才手写空值判断。
  • 必须:不得仅为判空新增依赖。
  • 推荐:项目没有现成判空工具时,对象使用 obj == null,集合使用 collection == null || collection.isEmpty()Map 使用 map == null || map.isEmpty();只有项目已经依赖 Apache Commons Collections 时,才使用 CollectionUtils.isEmpty()MapUtils.isEmpty()

OOP 与封装

  • 必须:遵循单一职责和最小可见性;字段默认 private,只暴露必要 API。
  • 必须:构造完成后对象应满足不变量;不要暴露可变内部集合、数组或日期对象。
  • 推荐:优先组合而非继承;继承只用于稳定的 is-a 关系和可替换契约。
  • 必须:覆写方法使用 @Override;可变参数只用于同类型、同语义参数,不使用 Object... 逃避类型设计。
  • 必须:构造器不得启动线程、访问远程资源或发布未完全构造的 this
  • 推荐:不可变对象优先;必要时使用 defensive copy,并确保集合元素也符合可变性预期。
  • 推荐:接口保持内聚,不创建囊括无关操作的“大而全” Service 或 Util。

API 与兼容性

  • 必须:公共 API 明确输入校验、返回语义、错误模型、幂等性和副作用。
  • 必须:单资源路径已经通过 @PathVariable 确定资源身份时,不得再使用可选查询参数表达另一套资源标识。不同标识的查询入口应拆分;若多个标识共同构成业务校验条件,应明确必填性、匹配规则和错误语义。
  • 必须:新增重载时检查 null、lambda、自动装箱和可变参数是否造成调用歧义。
  • 必须:修改 DTO、枚举、JSON 字段、RPC 签名或异常类型前评估调用方兼容性。
  • 推荐:返回接口类型而非具体集合实现;不要泄漏 ORM 实体、框架上下文或内部异常。
  • 推荐:避免布尔参数控制多个行为,优先使用有语义的方法、枚举或选项对象。
  • 必须:不得以反射、原始类型或未检查转换绕过编译器,除非边界隔离、理由明确并有测试。

Lombok

  • 必须:仅在项目已采用 Lombok 时使用,不为风格统一单独引入依赖。
  • 参考DTO/VO 可使用 @Data;使用前检查可变性、相等性和敏感字段,存在特殊约束时改用明确的 @Getter@Setter@EqualsAndHashCode@ToString
  • 推荐:实体类和值对象避免使用 @Data;按项目约定组合 @Getter@Setter@Builder@NoArgsConstructor@AllArgsConstructor,且不得绕过领域不变量或 ORM 构造约束。
  • 推荐:除非继承关系确有需要,不设置 @EqualsAndHashCode(callSuper = true)
  • 必须toString 不得暴露敏感字段,也不得触发懒加载或递归引用。