给定一个 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/