2

对于不可变对象,将包含的集合包装为不可修改的合适位置在哪里?我看到 3 个选项:

  1. 在不可变对象的工厂中:

    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. 在不可变的构造函数中

    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. 在不可变的访问器中(如果适用)。

    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;
        }
    }
    

还有其他选择吗?哪一个合适?

4

2 回答 2

4

我会说,如果您创建 Immutable 集合,那么您需要保护自己免受某人修改作为构造函数参数给出的列表,您应该保护性地复制它。

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

我个人很久以前就切换到Guava集合,因为在那里你可以找到不可变集合的接口。你的构造函数看起来像这样:

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

您可以确定您收到的参数不会被任何人修改。

在不可变类中保留对不可变列表的引用通常是一个好主意,因为这样可以保证您不会错误地修改它。

在我看来,案例(1)只有当工厂方法是创建不可变集合的唯一方法时才有意义,即使这样,当有人重构这些类时它也可能会中断。除非有其他限制,否则最好创建自给自足的类。

于 2012-09-16T21:53:40.067 回答
1

首先,您在所有地方的代码确实是不可变的,但这只是因为 anInteger是不可变的。
如果您有private final List<SomeCustomClass> values;,则Collections.unmodifiableList(values);不能保证SomeCustomClass列表中的个人是不可变的。必须为此编写代码。
话虽如此,另一种选择是对列表进行防御性深层复制。这种方法还提供了不变性。

于 2012-09-16T22:05:48.727 回答