如何为一个类中的私有变量定义一个“好的” get()方法?

时间:2019-07-10 16:53:41

标签: java

我正在学习Java,我对此有些怀疑。 如果定义了带有私有变量(如

)的类
class test<A>{
private A var;
...
public A get(){
    return var;
}

}

get方法错误吗? 我想是因为有了这个定义,我可以像这样修改变量“ var”

test<A> x = new test<A>();

A temp = x.get();

temp.set(*something*);

最后x改变了(我使用Vector作为A对其进行了测试)。如果我理解正确,那么这行得通是因为对象引用(我错过了C指针,sob)。我错了吗?也许我不明白关键字“私人”的目的!预先感谢!

编辑:“按引用传递”和“按值传递”没有问题。我有疑问为类中的私有变量定义get()方法(您不说吗?)。请停止链接Is Java "pass-by-reference" or "pass-by-value"?

4 个答案:

答案 0 :(得分:3)

如果您的getter方法正在返回对可变对象的引用,则这将大大削弱类提供的封装的质量,因为无需调用a即可修改类实例的状态。类的方法

防止这种问题的一种标准策略是J. Bloch所说的防御性副本(有效Java,第3版,条款50:“在需要时制作防御性副本”)。

这意味着在getter方法中创建var的副本,然后返回该副本。如何执行此操作取决于A的设计。

由于A是一个类型参数,因此要复制实例,需要在设计中提供其他支持。要了解如何使用Java的克隆机制来实现此目的,请参阅我的answer帖子“创建Copyable类型的接口而不是使用Cloneable有意义吗?”。

答案 1 :(得分:0)

如果遇到问题,您可以创建一个外观来保护您的变量

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");
  }
}

答案 2 :(得分:0)

这可能只是一开始的细节,但是您可以复习类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;
    }
}

答案 3 :(得分:0)

我还要在这里补充一点:正如其他人所说的那样,您可以分发对象引用,并且可以对其进行修改,这可能很糟糕。

面向对象是将数据及其上的代码保存在一个地方。如果需要getter,请考虑getter的调用者需要做什么,以及该操作是否应该是具有数据的类上的方法。您的代码可能会遇到Feature Envy的代码味道,因为它违反了Tell, Don't Ask原则。

要解决此问题,请删除吸气剂,并根据需要引入新方法。例如,如果您有一些需要打印的数据对象,则可以将打印机传递给该对象,然后将其自身打印到给定的打印机。

如果要处理集合类(只是从您的模板参数猜测而来),则可能需要保留吸气剂,但是您可能根本不关心调用者更改值。