1

最近在 Java 开发人员角色的采访中,有人问我如何使 Class A 不可变,如果它有一个成员变量,它是 Class B 的一个对象,并且在 Class B 是项目外部并且不能被编辑的情况下程序员此外 B 类甚至可能有一个自己的成员变量,它是另一个用户定义类的对象。我想了很多,并告诉面试官,除非 B 类已经实现并暴露了一个方法来深度克隆自己,否则没有办法。

但面试官并不相信。真的有办法让这样的类不可变吗?

如果我没记错的话,这就是他解释的情况。他希望我使 A 类不可变,最好的答案是什么?

final public class A {
    final private B b;

    A(B b) {
        this.b = b; // Class b might/might not be cloneable
        // this.b = (B)b.clone();
    }

    public B getB() {
        return b;
        // return (B)b.clone();
    }
}

class B // external cannot edit
{
    C c;

    public C getC() {
        return c;
    }

    public void setC(C c) {
        this.c = c;
    }
}

class C // external cannot edit
{
    int i;
    String j;

    public int getI() {
        return i;
    }

    public void setI(int i) {
        this.i = i;
    }

    public String getJ() {
        return j;
    }

    public void setJ(String j) {
        this.j = j;
    }
}
4

2 回答 2

2

不要将 B 暴露给世界。所以没有返回 B 的方法。

而是确定 B 中不会改变 B 的方法,并让 A 通过调用 b 中的相同方法来实现这些方法。

因此,如果 B 有一个方法 calcSomething(),a 应该有一个 calcSomething() 方法,它只返回 b.calcSomething()。

于 2015-11-30T18:39:21.407 回答
0

你可以使用这样的东西:

final public class A {
    final private B b;

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

    public B getB() {
        return cloneB(b);
    }

    private static B cloneB(b){ 
        B newB = new B(); 
        C c = new C();
        c.setI(b.getC().getI());
        c.setJ(b.getC().getJ());
        newB.setC(c); 
        return newB;
    }
}

在这种情况下,A 类是 100% 不可变的。

更新:您也可以使用反射或序列化来获取类的深层副本(如果类具有深层层次结构),例如使用 GSON 进行序列化:

private static B cloneB(b){ 
    String tmp = new GSON().toJson(b);
    return new GSON().fromJson(tmp, B.class);
}

等等

于 2015-11-30T18:52:41.767 回答