为清楚起见,将类设为 final 可以防止它被子类化。这在类不需要进一步细化的情况下很好。
将类级别变量标记为 final 意味着它只会被分配一次。对于像 String 这样的原语和不可变对象,这具有使变量不可变(默认情况下)的副作用。
但是,对于像 Date 这样的可变对象,您的变量将始终引用同一个实例,但其他有权访问该实例的人仍然能够更改它的状态。例如,如果你有一个方法
public Date getCreatedDate(){
return this.created; // class variable declared as private final Date created...;
}
然后任何调用者都可以访问创建的实例并更改它的状态。您最好只返回真正不可变的值,或者返回一个克隆。
public Date getCreatedDate(){
return this.created.clone();
}
编辑
“我将不可变数据模型类标记为 final,以确保更改其值的唯一方法是创建一个新实例”
据我了解,您的问题是 A 类依赖于 B 类。您希望测试 A 类并且您无法模拟 B 类,因为您已将其标记为最终。您将 Class B 标记为 final 以使其不可变(防止其内部状态被更改)。这是不正确的,因为将类标记为 final 会阻止它被子类化。它与更改实例内部状态的能力无关。
您对 final 的使用没有达到预期的效果。将字段标记为 final 不是一种选择,并且由于上述原因不会使类不可变。保护数据的唯一方法是防止数据的客户端访问构成其内部状态的对象。
假设您不是唯一的开发人员,您需要保护数据的用户免受意外更新。确保从 getter 返回克隆是一种方法。让团队成员子类和更改数据只是糟糕的编程,不是无意的,并且可以通过策略和代码审查来管理。
如果您希望保护您的代码免受未知开发人员的外部干扰(例如编写使用相同命名空间来注入其代码的代码),则可以使用其他方法,例如包密封。