我的讲师说如果类有私有变量,当你想通过getter返回那些变量的值时,如果它们的数据类型是原始的,你可以直接返回它们的值,但如果它们是引用类型,一般的经验法则是你应该几乎总是返回Object.clone()。然后我想知道在什么情况下你不需要返回Object.clone()?
答案 0 :(得分:4)
但如果它们是引用类型,一般的经验法则是你应该几乎总是返回Object.clone()。
不鼓励使用克隆。可能你的意思是创建对象的副本(深)并返回。
然后我想知道你不需要返回Object.clone()?
每当您想允许班级的来电者修改班级数据时。
Inshort,如果是可变对象。
答案 1 :(得分:1)
如果成员是不可变的引用类型,例如String
,Integer
等......则无需在getter方法中创建实例变量的副本。
当实例变量是可变的时,返回原始值允许getter方法的调用者在不调用setter方法的情况下改变对象。这通常是一种不好的做法,并且可能导致很难发现错误。
答案 2 :(得分:1)
...如果它们是引用类型,一般的经验法则是你应该几乎总是返回
Object.clone()
您可能想制作副本,但不一定要使用Object.clone
。这通常称为制作防御性副本。
考虑这个课程:
import java.util.List;
import java.util.LinkedList;
class Foo {
private List<String> list;
private String info;
public Foo(String info) {
this.list = new LinkedList<String>();
this.info = info;
}
public List<String> getList() {
return this.list;
}
public String getInfo() {
return this.info;
}
}
getList
和getInfo
都没有将它返回给调用者的对象的副本,它们返回对该对象的引用。在getList
的情况下,这意味着使用该类的代码可以执行此操作:
List<String> theList = foo.getList();
theList.add("Hi there");
...更改foo
内的列表状态,而不使用任何foo
mutator方法(getList
不是变异方法)。
在getInfo
的情况下,由于字符串是不可变的,调用者无法对字符串的引用做任何改变foo
的状态。< / p>
然后我想知道你不需要返回Object.clone()?
如果您要返回的内容是不可变的(例如String
),则无需制作防御副本。
如果您希望班级用户能够在不使用foo
方法的情况下更改foo
的状态,则您不希望制作防御性副本。
如果您要返回的内容是可变的(例如List
)并且不希望调用者能够更改它,那么:
可能通过包装器(例如来自Collections.unmodifiableList
)返回它的不可变版本。
返回它的防御副本。
由于副本可能很昂贵,因此您需要同时选择Foo
的API以及如何处理其中包含的对象,并着眼于内存使用和性能如果有好的话这些将成为使用课程的一个因素。