对不可变 类 使用 final private 或 private setter

Using final private or private setters for immutable classes

我正在阅读 here 以创建不可变对象,我想知道,我有以下内容 class:

final public class AnonymousCilent {

    final private String anonymousCilentID;

    public AnonymousCilent(String anonymousCilentID) {
        this.anonymousCilentID = anonymousCilentID; 
    }

这是 Oracle 建议创建不可变 classes 的方式,但是,在 C# 中,您可以将 setter 声明为私有,在 Java 中,如果我这样做,它仍然是不可变的吗?

private String anonymousCilentID;

public AnonymousCilent(String anonymousCilentID) {
    this.setAnonymousCilentID(anonymousCilentID);
}

public String getAnonymousCilentID() {
    return anonymousCilentID;
}

private void setAnonymousCilentID(String anonymousCilentID) {
    this.anonymousCilentID = anonymousCilentID;
}

实现私有 setter 而不是将我的私有变量设置为 final 并使用构造函数有什么问题?

原因是将方法设置为私有只影响方法的范围。如果你想要一个真正不可变的变量,那么你也必须将它设置为 final。这样你的变量就不会被改变。

您还可以 return 在 getAnonymousClientID 方法中克隆您的用户 ID。

默认情况下,Java 中的所有对象都是可变的。

编辑: 所以你要做的就是 return 你的 userID 在你的 get 方法中,像这样:

public String getUserID() {
    return (String) userID.clone();
}

私人 setter 完全没有意义。任何可以调用私有 setter 的代码也可以直接写入变量。这意味着无法保证,只是因为您将 setter 设为私有,该代码不会修改变量。

创建字段 final 做两件事:

  • 需要通过构造函数设置值(或至少在构造时解析)
  • 禁止为字段
  • 创建setter

只要字段中的数据类型不是可变的(如数组),就足以使对象不可变。不可变 class 基本上意味着它的状态在实例化后不能改变,如果有任何改变,它会产生一个新的对象实例。

写一个 setter 方法只是为了让它成为私有有什么意义?没有意义,它在构造函数中的使用会阻止您将字段声明为 final。将字段声明为 final 非常有用,因为它向 reader 表明您永远不会修改该字段的意图,如果您再次尝试修改该字段,它也会导致编译错误,并且它还可能允许进行额外的优化。

使用 final 字段。

final 放在字段上会告诉任何阅读您的代码的开发人员 class 是不可变的 - 这很好。

但是,具有可变字段(私有 setter 或不私有)表明只要实例本身更改它就可以更改值。即其他一些程序员可能会出现并添加一个变异方法,例如下面的clear()

private String anonymousCilentID;

public AnonymousCilent(String anonymousCilentID) {
    this.setAnonymousCilentID(anonymousCilentID);
}

public String getAnonymousCilentID() {
    return anonymousCilentID;
}

private void setAnonymousCilentID(String anonymousCilentID) {
    this.anonymousCilentID = anonymousCilentID;
}

// This method seems reasonable, but it isn't OK    
public void clear() {
   anonymousCilentID = null;          //   <--- opps!
}

这很糟糕。