对不可变 类 使用 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!
}
这很糟糕。
我正在阅读 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!
}
这很糟糕。