4 回答
TA贡献1757条经验 获得超8个赞
如果您的 getter 方法返回对可变对象的引用,那么这会大大削弱您的类提供的封装质量,因为可以在不调用类的方法的情况下修改类实例的状态。
防止此问题的一种标准策略是 J. Bloch 所说的防御性副本(Effective Java,第 3 版,第 50 项:“在需要时制作防御性副本”)。
var
这意味着在 getter 方法中创建一个副本,然后返回该副本。如何做到这一点取决于A
.
因为A
是类型参数,制作实例的副本需要设计上的额外支持。要了解如何使用 Java 的克隆机制实现此目的,请参阅我对帖子“创建类型接口而不是使用有意义吗?”的回答。Copyable
Cloneable
TA贡献1856条经验 获得超17个赞
我要在这里补充一点:正如其他人所说,您分发对象引用并且可以对其进行修改,这可能很糟糕。
面向对象是关于将数据和处理数据的代码保存在一个地方。如果您需要 getter,请考虑 getter 的调用者需要做什么,以及该操作是否应该是具有数据的类上的方法。您的代码可能会遇到Feature Envy代码异味,因为它违反了告诉,不要询问原则。
要解决此问题,请移除 getter,并根据需要引入新方法。例如,如果您有一些需要打印的数据对象,您可以将 Printer 传递给对象并让它自己打印到给定的 Printer。
如果你正在处理一个集合类(只是从你的模板参数中猜测),你可能需要保留 getter,但是你可能并不关心调用者无论如何都会改变值。
TA贡献2051条经验 获得超10个赞
对于刚开始的人来说,这可能有点过于详细,但您可能会回顾 class java.util.concurrent.atomic.AtomicReference<V>,这与您的示例非常相似。
一般来说,将实例变量放在私有变量中,同时使用 getter 和 setter 提供对变量的访问是标准做法。
请注意,您的类名应该大写,类型参数“V”更标准,变量名通常是“值”。此外,尝试为班级选择一个更具交际性的名称。(类型参数类型变量可以是“ValueType”,这符合某些偏好。但是,单个字符类型变量名称更常见。)
public class Wrapper<V> {
private V value;
public V get() {
return value;
}
public void set(V value) {
this.value = value;
}
}
TA贡献1829条经验 获得超6个赞
如果这是一个问题,您可以创建一个外观来保护您的变量
public class Facade extends A {
A myObj;
public Facade (A obj) {
myObj =
}
public A get(){
return myObj.get();
}
public B set(Object val) {
throw new RuntimeException("Setting is not allowed");
}
}
添加回答
举报