简体   繁体   中英

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?

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. This way your variable cannot be mutated.

You could also return a clone of your userID in the getAnonymousClientID method.

All objects are mutable by default in Java.

EDIT: So all you would do is return your userID in your get method like this:

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

Making the field final does two things:

  • 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.

What is the point of writing a setter method only to make it private? There is no point and its usage in the constructor prevents you from declaring the field 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.

Use a final field.

Putting final on a field tells any developer reading your code that the class is immutable - which is good.

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:

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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