Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/324.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何定义一个;“好”;类中私有变量的get()方法?_Java - Fatal编程技术网

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

Java 如何定义一个;“好”;类中私有变量的get()方法?,java,Java,我正在学习Java,我有一些疑问。 如果定义了一个带有私有变量的类,如 class test<A>{ private A var; ... public A get(){ return var; } 类测试如果这是一个问题,您可以创建一个façade来保护您的变量 public class Facade extends A { A myObj; public Facade (A obj) { myObj = } public A get(){

我正在学习Java,我有一些疑问。 如果定义了一个带有私有变量的类,如

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

类测试

如果这是一个问题,您可以创建一个façade来保护您的变量

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

如果getter方法返回对可变对象的引用,那么这将大大削弱类提供的封装质量,因为不调用类的方法就可以修改类实例的状态

防止这个问题的一个标准策略是J.Bloch所称的防御性拷贝(有效Java,第3版,第50项:“在需要时制作防御性拷贝”)

这意味着在getter方法中创建
var
的副本,并返回该副本。如何做到这一点取决于
A
的设计


由于
A
是一个类型参数,因此制作实例的副本需要在设计中提供额外的支持。要了解如何使用Java的克隆机制实现这一点,请参阅我的文章“创建一个
可复制的
类型接口而不是使用
可克隆的
”是否有意义?

对于刚开始的人来说,这可能有点太详细了,但您可以查看类
Java.util.concurrent.atomic.AtomicReference
,这和你的例子很相似

一般来说,在私有变量中放置实例变量,同时使用getter和setter提供对变量的访问,这是标准做法

请注意,类名应该大写,类型参数“V”更为标准,变量名通常为“value”。另外,试着为班级选择一个更具交际性的名字。(类型参数类型变量可以是“ValueType”,这符合某些首选项。但是,单字符类型变量名称更常见。)

公共类包装器{
私人价值;
公共V get(){
返回值;
}
公共无效集(V值){
这个值=值;
}
}

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

面向对象是将数据和处理数据的代码放在一个地方。如果需要getter,请考虑getter的调用方需要做什么,以及该操作是否应该是具有数据的类上的方法。您的代码可能会受到代码气味的影响,因为它违反了原则

要解决这个问题,请删除getter,并根据需要引入新方法。例如,如果需要打印某个数据对象,可以将打印机传递给该对象,并将其自身打印到给定的打印机


如果您处理的是集合类(只是模板参数的猜测),则可能需要保留getter,但您可能并不关心调用方如何更改值。

这一切都取决于您想做什么。其他类,如
TreeSet
也有同样的问题,底层类可能会发生变化。正确使用它们取决于程序员。x是一个传递的值,它实际上并没有改变实际值,而是一个值的副本。但是在这种情况下,“private”并不是很有用,表示会出现错误!我认为这种定义get的方法很好,因为x是一个基本类型变量。另一种选择是使
a
类成为只读/不可变版本(要么是一个接口,只有
getter
,要么是一个简单的视图,它从
a
的实例构造自己),然后从
get
方法返回它。这完全取决于
A
是什么,“只读/不可变版本o…”是一个好方法,但我认为“通常”如果x是公共的,则更容易定义get(),否则返回(深度)副本。这也是用Java编写代码的好方法吗?谢谢。如果x是公共的,则可以“正常”定义get(),否则返回(深度)副本?这是用Java编写代码的好方法吗?我是Java的“初学者”。@HegManga这一切都取决于方法的要求。并非每个对象都需要是不可变的。是否提供getter更多地取决于对象类型要呈现的API。将“getX”视为必需行为,“private V value”视为实现必需行为的方式。通常,实现对API是隐藏的。这使实现者可以在不破坏API的情况下更改实现。目前,我不想讨论复制问题。有太多的问题需要解释,而且它们不会很好地停留在一开始的水平。值得介绍的主要情况是何时返回集合类型值,以及调用方是否应该能够更新返回的集合。在许多情况下,禁止对返回的集合进行调用方更新。但是,安全返回集合类型值的方法不是复制集合。这可能是非常低效的。更好的是,java提供了不可修改的集合,例如“collections.unmodifiableSet(aSet)”。感谢您的提示!
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");
  }
}
public class Wrapper<V> {
    private V value;
    public V get() {
        return value;
    }
    public void set(V value) {
        this.value = value;
    }
}