java - 我是否总是需要克隆一个对象以确保 Java 中的封装?

标签 java encapsulation

给定一个 Outer 类,它将对 Inner 类的对象的引用作为参数:

public class Outer {

    private Inner inner;

    public Outer(Inner inner) {
        // fails
        // this.inner = inner;

        // passes
        this.inner = this.clone(inner);
    }

    public Inner getInner() {
        return this.inner;
    }

    private Inner clone(Inner inner) {
        return new Inner(inner.getInnerValue());
    }
}

和只有整数值的Inner

public class Inner {

    private int innerValue;

    public Inner(int innerValue) { this.innerValue = innerValue; }

    public void setInnerValue(int innerValue) {
        this.innerValue = innerValue;
    }

    public int getInnerValue() {
        return this.innerValue;
    }
}

测试

class OuterTest {
    @Test
    void testEncapsulation() {
        Inner inner = new Inner(3);
        Outer outer = new Outer(inner);
        inner.setInnerValue(4);
        assertEquals(3, outer.getInner().getInnerValue());
    }
}

仅当我克隆内部时才通过(请参阅注释失败)。一般情况下是这样吗?那么,每当我传递一个引用时,我都需要克隆每个引用吗?

最佳答案

不,并不总是。

另一种方法是让所有 setter 都为 Inner返回 Inner 的新实例,而不是设置 this 字段。通常这些 setter 将具有名称“+”,例如 withInnerValue :

public Inner withInnerValue(int innerValue) {
    return new Inner(innerValue);
}

然后在测试中,您将被迫这样做:

void testEncapsulation() {
    Inner inner = new Inner(3);
    Outer outer = new Outer(inner);
    inner = inner.withInnerValue(4); <---- this is forced to change
    assertEquals(3, outer.getInner().getInnerValue());
}

通过重写Inner的 setter ,您已将其设为不可变,也就是说,一旦创建实例,其字段就无法更改。

关于java - 我是否总是需要克隆一个对象以确保 Java 中的封装?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57832763/

相关文章:

内存压力

具有调用私有(private)方法的静态方法的 Ruby 类?

java - 封装常见的异常处理逻辑

c++ - 我如何在 C++ 中封装供一般客户使用的合并排序程序?

c++ - 重载 << 运算符 - 多个参数

java - Android隐藏类的实现?

java - BigDecimal 赋值运算符

Java InputMap 不注册 Shift 按键

java - 在应用程序之间传递 java 邮件消息对象

java - 将 LinkedHashSet 转换为列表