Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/390.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何维护引用可变对象的类的不变性质?_Java_Immutability - Fatal编程技术网

Java 如何维护引用可变对象的类的不变性质?

Java 如何维护引用可变对象的类的不变性质?,java,immutability,Java,Immutability,我很清楚使类不可变的规则。但是考虑一个情况,我的类A组成B类B类在外部jar和B类中再次组成C和D,即 class A{ B b; } // External library class B{ C c; D d; } class C{ } class D{ } 如果不能修改外部库中的类,如何使类A不可变?如果外部库中的类是可修改的,我可以实现可克隆的,但这是不可能的,因为我不能修改它们。类A不应该允许访问任何可变引用 下面是您的课堂示例: class A { private

我很清楚使类不可变的规则。但是考虑一个情况,我的类A组成B类B类在外部jar和B类中再次组成C和D,即

class A{
  B b;
}
// External library
class B{
  C c;
  D d;
}
class C{
}
class D{
}

如果不能修改外部库中的类,如何使类A不可变?如果外部库中的类是可修改的,我可以实现可克隆的,但这是不可能的,因为我不能修改它们。

类A不应该允许访问任何可变引用

下面是您的课堂示例:

class A {

  private final B b;

  public A(B b) {
    this.b = b;
  }

  // no public access to B reference that's final.  No changing it from the outside.  A is immutable.
}

类B、C和D来自库。如果你给A一个可变的引用,并允许代码的其余部分改变B或它的C和D子项的状态,那就没什么可做的了。但是,如果您正确地构造了B并将其委托给A,那么其他人将无法更改其状态。

您应该创建可变实例的防御副本:

class A {

    private final B b;

    public A(B b) {
        // Create a defensive copy of b
        this.b = new B(b);
    }
}
如果
B
没有提供这样的复制构造函数,则需要自己为
B
实现防御复制


如果您不这样做,我可以将
B
的实例传递给
A
,但也可以将
B
的实例保留给我自己,并在以后根据我的意愿对其进行修改。

很明显:不要让A类以外的任何人访问可变引用。不允许A将其引用更改为B、C或D。您能用示例代码解释一下吗?请参阅下面的答案。客户端代码是否需要访问
B
?-ie是否有一个
public B getB()
方法?@Bohemian是的,它有一个
B
的实例,我可以传递给
a
并保留
B
的实例。我可以稍后对
B
的实例进行变异。创建一个其他人无法使用的实例。你可以这样做,但它破坏了你的目标效果。这是你的代码-做需要做的事情。我的观点是,
A
根据你发布的代码,即使它不允许访问任何可变引用,也可以进行变异。你的答案是简单的“不要做”,在我看来,这是很弱的。我们应该在这里考虑两个角色——希望使<代码> <代码>的OP真的不变。以及想要变异
A
的恶意开发者。有了这个答案,Dev将能够伤害。事实上,它是弱小的。你关于B的拷贝构造函数和防御拷贝的观点真的很好。有价值的贡献。在这种情况下,我们不应该提供任何getter(getB())。因为如果我可以通过调用getB().getC()访问getter方法,我可以再次变异C和D(假设B的getter为C)。这是正确的理解吗?@AnkitPandoh是的,保密。如果公开
B
的实例,则可以从外部修改它们。