不可变类,参考可变类

时间:2014-03-19 07:36:35

标签: java mutable

假设我正在创建一个具有可变类引用Address的不可变类Employee。我们如何用场景创建不可变类。

我只是参考此链接click here。我不明白这一点:

  

不要共享对可变对象的引用。永远不要存储参考   传递给构造函数的外部可变对象;如有必要,   创建副本,并存储对副本的引用。同样,创造   必要时避免使用内部可变对象的副本   在你的方法中返回原件。

3 个答案:

答案 0 :(得分:4)

如果要将可变对象封装到不可变对象中,则需要:

  • 创建可变对象的副本(即通过复制构造函数,克隆,序列化/反序列化等);永远不要存储对原始可变对象的引用。
  • 永远不要返回可变对象。如果必须,则返回该对象的副本。
  • 避免使用可以更改可变对象的方法

参考:A Strategy for Defining Immutable Objects - The Java tutorials

答案 1 :(得分:1)

您无法违反Address班级合同。

相反,您可以创建一个我称之为ImmutableAddress的新类,并让它在其构造函数中接受Address并从中获取相关信息,从而为该信息公开getter,但没有制定者。 (重要的是你不要只存储Address;你必须从中获取信息并存储它,因为你不能信任任何不修改{{1}的信息。你得到了)。然后在Address上使用ImmutableAddress而不是Employee

现在,尽管如此,可悲的事实是你看到类合同在运行时异常中经常被破坏。你这样做的方法是子类Address并让它的所有setter抛出一个运行时异常,然后构造你的子类,引用传入的Address。但这是一个黑客,更好地创建新的,真正不可改变的类。

答案 2 :(得分:0)

您需要创建Address类的不可变副本,并在Employee类中使用它。例如:

public final class ImmutableAddress
{
    private final String street;

    public ImmutableAddress(final Addres addr)
    {
        Objects.checkNotNull(addr, "null arguments not accepted");
        street = addr.getStreet();
    }

    // Alternate, static constructor
    public static ImmutableAddress from(final Address addr)
    {
        return new ImmutableAddress(addr);
    }

    public String getStreet() { return street; }
}

然后在Employee的构造函数中执行:

private final ImmutableAddress addresss;

public Employee(final Address addr)
{
    address = ImmutableAddress.from(addr);
}