我正在阅读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有什么问题,而不是让我的私有变量最终,并使用构造函数?
答案 0 :(得分:3)
原因是将方法设置为private仅影响方法的范围。如果你想要一个真正不可变的变量,那么你也必须将它设置为final。这样你的变量就不会发生变异。
您还可以在getAnonymousClientID方法中返回userID的克隆。
默认情况下,所有对象在Java中都是可变的。
编辑: 所以你要做的就是在你的get方法中返回你的userID:
public String getUserID() {
return (String) userID.clone();
}
答案 1 :(得分:1)
使字段final
做两件事:
如果字段中的数据类型不可变(如数组),则应该足以使对象不可变。不可变类基本上意味着它的状态在实例化后不能被改变,如果有任何改变,它将产生一个新的对象实例。
答案 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!
}
这很糟糕。