如何在JAVA中使返回不可变

时间:2014-10-08 14:51:30

标签: java immutability

我有一个像

这样的对象
public class ABC {

    private String a;
    private String b;
    private String c;

    //getters and setters    
}

此对象从诸如ArrayList<ABC>

之类的集合中的方法返回

我只想让返回不可变而不改变对象中的任何内容。有人可以帮我这个吗?

3 个答案:

答案 0 :(得分:4)

不要提供setter(mutators),将不可变属性设为私有,只通过构造函数提供值赋值。

您始终可以声明不可变属性final。因此,您只能为其分配一次值,以后无法更改它们。

答案 1 :(得分:1)

仅使用具有getter的接口

A是你的具体(impl)类

Coding to interfaces?

public I getA(){ retrun AImpl();}

,其中

public interface I { public String getOne()}
public AImple implements I {...}

当前课程中唯一的“改变”是“实施我”

JDK和Apache commons使用装饰器

http://grepcode.com/file/repository.jboss.org/nexus/content/repositories/releases/org.jboss.embedded/thirdparty-all/beta3.SP15/org/apache/commons/collections/list/UnmodifiableList.java

另一种解决方案

克隆您的对象并将其返回,这样就可以更改副本并保持原始对象不变

答案 2 :(得分:0)

如果对象提供了变异,则无法使对象成为不可变对象。对象始终提供其类定义的所有功能。

因此,如果你想要一个不可变对象,那么你需要一个不可变的类。如果你不能改变有问题的类,那么所描述的包装类(例如@duffymo)可以用于此目的。但是请注意,这样一个类的对象可以与包装类的对象互换,并且还需要提供应用包装器的方式。

如果你需要与ABC类对象完全互换的对象,那么你就会坚持ABCs是可变的这一事实,因此任何可与ABCs互换的东西都是可变的,至少在ABC的可变方面是这样。 。然后归结为你想要不变性的原因。如果要避免改变List引用的对象,那么复制这些对象(适当的深度)是另一种选择。

作为第三种选择,如果目标类没有非私有字段,那么您可以创建一个子类,覆盖setter无效或抛出一些未经检查的异常。在这种情况下,请注意

  1. 这样的子类不是好的形式,它的实例不能与ABC类的实例真正互换。
  2. 如果ABC类具有可变类型的可访问属性(例如,可变容器),那么您可能需要做一些事情来防止这些对象发生变异。递归。
  3. 是的,这是一个很大的混乱。