使用最终私有或私有setter用于不可变类

时间:2015-07-03 17:02:17

标签: java immutability

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

final public class AnonymousCilent {

    final private String anonymousCilentID;

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

这是Oracle建议创建不可变类的方式,但是,在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有什么问题,而不是让我的私有变量最终,并使用构造函数?

5 个答案:

答案 0 :(得分:3)

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

您还可以在getAnonymousClientID方法中返回userID的克隆。

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

编辑: 所以你要做的就是在你的get方法中返回你的userID:

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

答案 1 :(得分:1)

使字段final做两件事:

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

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

编写setter方法只是为了使它成为私有的重点是什么?没有意义,它在构造函数中的用法会阻止您声明字段final。声明最终字段是有用的,因为它向读者显示您的意图永远不会修改该字段,如果您再次尝试修改该字段,它也会导致编译错误,并且它还可能允许其他优化。

答案 4 :(得分:0)

使用final字段。

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

但是,拥有一个可变字段(私有设置器或非私有设置器)表示只要实例本身更改它就可以更改该值。即一些其他程序员可能会出现并添加一个变异方法,如下面的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!
}

这很糟糕。