Is this class completely immutable?

I am trying to convert a modified class to a Nonutable class, following the tips given in Effective Java Element 15 (minimizing reciprocity). Can someone tell me if the class I created is created? completely unchanged or not?

Mutable class

public class Record { public int sequenceNumber; public String id; public List<Field> fields; /** * Default Constructor */ public Record() { super(); } public Record addField(Field fieldToAdd) { fields.add(fieldToAdd); return this; } public Record removeField(Field fieldToRemove) { fields.remove(fieldToRemove); return this; } public int getSequenceNumber() { return sequenceNumber; } public String getId() { return id; } public List<Field> getFields() { return fields; } public void setSequenceNumber(int sequenceNumber) { this.sequenceNumber = sequenceNumber; } public void setFields(List<Field> fields) { this.fields = fields; } public void setId(String id) { this.id = id; } } 

Field class

 public class Field { private String name; private String value; public Field(String name,String value) { this.name = name; this.value = value; } public String getName() { return name; } public String getValue() { return value; } } 

Immutable class

 public class ImmutableRecord { private final int sequenceNumber; private final String id; private final List<Field> fields; private ImmutableRecord(int sequenceNumber, List<Field> fields) { this.sequenceNumber = sequenceNumber; this.fields = fields; this.id = UUID.randomUUID().toString(); } public static ImmutableRecord getInstance(int sequenceNumber, List<Field> fields) { return new ImmutableRecord(sequenceNumber, fields); } /********************* Only Accessor No Mutator *********************/ public int getSequenceNumber() { return sequenceNumber; } public String getId() { return id; } public List<Field> getFields() { return Collections.unmodifiableList(fields); } /********************* Instance Methods *********************/ public ImmutableRecord addField(Field fieldToAdd) { Field field = new Field(fieldToAdd.getName(), fieldToAdd.getValue()); List<Field> newFields = new ArrayList<Field>(fields); newFields.add(field); Collections.unmodifiableList(newFields); ImmutableRecord immutableRecord = new ImmutableRecord(sequenceNumber, newFields); return immutableRecord; } public ImmutableRecord removeField(Field fieldToRemove) { Field field = new Field(fieldToRemove.getName(), fieldToRemove.getValue()); List<Field> newFields = new ArrayList<Field>(fields); newFields.remove(field); Collections.unmodifiableList(newFields); ImmutableRecord immutableRecord = new ImmutableRecord(sequenceNumber, newFields); return immutableRecord; } } 

thanks

Shekhar

+4
source share
3 answers

As indicated by the icus, the fields argument in the constructor can be changed outside the class. It may also be a "non-standard" List implementation. Thus,

  this.fields = fields; 

should be changed to

  this.fields = new ArrayList<Field>(fields); 

or maybe

  this.fields = Collections.unmodifiableList(new ArrayList<Field>(fields)); 

There are pros and cons to creating an immutable list box. First of all, it says what you mean. It prevents errors / maintenance engineers. Allocation is a bit and a miss - you do not allocate each time you receive it; Distributions are optimized (potentially analyzed analysis); having objects hanging around is not a good idea because it slows down garbage collection (and consumes memory to a much lesser extent).

Also do all the classes and fields - say what you mean, and there are some subtleties.

The "add" methods are fine. Take a look at BigInteger , say it (although ignore some of its features!).

A somewhat controversial point of view is that everything that get in those access methods in an immutable class is a nuisance. Remove get .

Creating a private constructor and adding a static creation method named of adds a bit, but you almost never need a β€œnew” object. Type inference is also allowed before we get the diamond operator currently in JDK7. private constructors also allow you to remove copy variables when creating a new instance in addField and removeField .

equals , hashCode and maybe toString nice to have. Although the API has YAGNI vs construct interfaces (the concept, not the Java keyword).

+2
source

No, it is not, list fields must be copied and direct link not saved

 private ImmutableRecord(int sequenceNumber, List<Field> fields) { this.sequenceNumber = sequenceNumber; this.fields = fields; // breaks immutability!!! this.id = UUID.randomUUID().toString(); } 

If someone modifies a reference to List fields, your class will also reflect it. It’s better to copy the contents of the collection to another before proceeding with this.fields

Also your class is appears mutable, as it adds and removes methods :)

+11
source

"1. Do not specify any methods that modify the object (known as mutators).

  1. Make sure that no methods can be overridden. This prevents unwanted or malicious subclasses from compromising the immutable behavior of the class. Preventing method overrides is usually done by creating the final class.

  2. Make all fields final. This clearly expresses your intentions in the way that the system applies. In addition, it may be necessary to ensure correct behavior if a link to a newly created instance is transferred from one thread to another without synchronization, depending on the results of ongoing efforts to process the memory model.

  3. Make all fields private. This prevents clients from changing fields directly. Although it is technically permissible for immutable classes to have publicly accessible final fields containing primitive values ​​or references to immutable objects, this is not recommended, since this excludes changing the internal representation in a later version (clause 12).

  4. Provide exclusive access to any mutable components. If your class has fields related to mutable objects, make sure that class clients cannot get references to these objects. Do not initialize such a field to refer to the object provided by the client, and do not return the link to the object from the accessor. Create protective copies (paragraph 24) in the constructors, accessories, and readObject methods (paragraph 56).

http://wiki.glassfish.java.net/attach/JavaProgramming/ej.html#immutablerecipe

+1
source

All Articles