简体   繁体   English

对不可变类使用最终的私有或私有二传手

[英]Using final private or private setters for immutable classes

I was doing some reading here for creating immutable objects, and I was wondering, I have the following class: 我在这里阅读一些有关创建不可变对象的信息,我想知道我有以下课程:

final public class AnonymousCilent {

    final private String anonymousCilentID;

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

This is the way Oracle suggests to create immutable classes, however, in C# you can declare your setter private, in Java is it still immutable if I do this? 这是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;
}

What is wrong with implementing a private setter, instead of making my private variable final, and using a constructor? 实现私有设置程序而不是使私有变量最终定型并使用构造函数有什么问题?

The reason is that setting the method private only effects the scope of the method. 原因是将方法设置为私有仅影响方法的范围。 If you want a truly immutable variable then you must set it final as well. 如果您想要一个真正不变的变量,那么还必须将其设置为final。 This way your variable cannot be mutated. 这样,您的变量就无法突变。

You could also return a clone of your userID in the getAnonymousClientID method. 您还可以在getAnonymousClientID方法中返回您的userID的克隆。

All objects are mutable by default in Java. 默认情况下,Java中所有对象都是可变的。

EDIT: So all you would do is return your userID in your get method like this: 编辑:因此,您要做的就是在您的get方法中返回您的userID,如下所示:

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

Making the field final does two things: 将字段定为final有两件事:

  • Requires the value to be set through the constructor (or at least be resolved at construction time) 要求通过构造函数设置值(或至少在构造时解析)
  • Prohibits the creation of a setter for the field 禁止为现场创建二传手

Provided that the datatype at the field isn't mutable (like an array), that should be sufficient to make the object immutable. 假设字段中的数据类型是不可变的(如数组),则应足以使对象不可变。 An immutable class basically means that its state can't be changed after it's instantiated, and if there are any changes, it would produce a new instance of the object. 不变类基本上意味着实例化后其状态不能更改,并且如果有任何更改,它将产生该对象的新实例。

A private setter is completely pointless. 私人二传手是完全没有意义的。 Any code that can call the private setter can also write to the variable directly. 任何可以调用私有设置程序的代码也可以直接写入变量。 That means there is no guarantee, just because you made the setter private, that code doesn't modify the variable. 这意味着不能保证,仅因为您将setter设为私有,代码就不会修改变量。

What is the point of writing a setter method only to make it private? 编写一个setter方法只是为了使其私有化有什么意义? There is no point and its usage in the constructor prevents you from declaring the field final. 没有意义,在构造函数中使用它会阻止您将字段声明为final。 Declaring the field final is useful as it shows your intentions to the reader never to modify that field, it will also cause a compile error if you ever try to modify that field again, and it may also allow additional optimizations. 声明字段final很有用,因为它向读者表明了您永远不要修改该字段的意图,如果您再次尝试修改该字段,它也会导致编译错误,并且还可能允许进行其他优化。

Use a final field. 使用final字段。

Putting final on a field tells any developer reading your code that the class is immutable - which is good. final放在字段上会告诉所有阅读您的代码的开发人员该类是不可变的-很好。

However, having a mutable field (private setter or not) suggests it's OK to change the value as long as the instance itself changes it. 但是,具有可变字段(是否有私有设置程序)表明,只要实例本身对其进行更改,就可以更改该值。 ie some other programmer may come along and add a mutating method ,like clear() below: 即其他一些程序员可能会出现并添加一个变异方法,例如下面的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!
}

This is bad. 这不好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM