Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

With an immutable object, where is it proper to wrap a contained collection as unmodifiable? I see 3 options:

  1. In the immutable object's factory:

    public class ImmutableFactory {
    
        public Immutable build(){
           List<Integer> values = new ArrayList<Integer>();
    
            values.add(1);
            values.add(2);
            values.add(3);
    
            return new Immutable(Collections.unmodifiableList(values), "hello");
        }
    }
    
  2. In the immutable's contructor

    public class Immutable {
    
        private final List<Integer> values;
        private final String hello;
    
        public Immutable(List<Integer> values, String hello) {
            this.values = Collections.unmodifiableList(values);
           this.hello = hello;
        }
    
        public List<Integer> getValues() {
            return values;
        }
    
        public String getHello() {
            return hello;
        }
    }
    
  3. In the immutable's accessor (if applicable).

    public class Immutable {
    
        private final List<Integer> values;
        private final String hello;
    
        public Immutable(List<Integer> values, String hello) {
            this.values = values;
            this.hello = hello;
        }
    
        public List<Integer> getValues() {
            return Collections.unmodifiableList(values);
        }
    
        public String getHello() {
            return hello;
        }
    }
    

Are there any other options and which one is proper?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
566 views
Welcome To Ask or Share your Answers For Others

1 Answer

I'd say if you create Immutable collection then you need to protect yourself from somebody modifying list that was given as an argument to constructor, you should protectively copy it.

public Immutable(List<Integer> values, String hello) {
    this.values = Collections.unmodifiableList(new ArrayList<Integer>(values));
    this.hello = hello;
}

I personally have long ago switched to Guava collections as there you can find interfaces for immutable collections. Your constructor would look like that:

public Immutable(ImmutableList<Integer> values, String hello) {
    this.values = values;
    this.hello = hello;
}

You'd be sure that argument you receive will not be modified by anyone.

It is usually a good idea to keep reference to immutable list within your immutable class as it then guarantees that you don't modify it by mistake.

Case (1) in my opinion makes sense only when factory method is the only way to create the immutable collection and even then it may break when someone refactors these classes. Unless there are other limitations it is always best to create self-sufficient classes.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...