如何在调用者无法编辑返回对象的地方实现 getter?
How do I implement a getter where the caller can't edit the returned object?
我想制作一个 getter 不允许调用者编辑 returned 对象。
以 List
为例(尽管我希望答案也适用于任何其他类型),这是 returning 和编辑属性的常用方法:
class MyClass {
private List<String> strings;
// to get the whole object
public List<String> getStrings() {
return this.strings;
}
// to alter the object
public void addString(String newStr) {
this.strings.add(newStr);
}
//...
}
然而,这并不能阻止其他一些 class 这样做
myClassInstance.getStrings().add("that's a dumb implementation, bro");
这有点粗鲁,因为我为此特定目的创建了 addString()
。
我宁愿其他 classes 只使用 getStrings()
方法来读取,因为可能有类似的情况我不想实现 addString()
方法。在那种情况下,其他 classes 无论如何都可以通过 getter 编辑 strings
,但我仍然希望能够在 C
[=] 中私下编辑对象56=].
我知道如果属性是原始类型这不会有问题,因为它们直接保存在实例中,但对象是对内存的引用,所以任何 class 能够得到它的手如果对象类型允许,可以对这些引用进行编辑。
我可以相信其他 class 不会尝试通过 getter 编辑我的对象吗?
可以选择克隆它(某些 classes 可能会覆盖 clone()
method),但这对 clone()
有用吗?克隆对象的最佳实践是什么?
是否值得创建一个只能在构造函数中写入的自定义 class(在本例中称为 ReadOnlyList
)(如 this) , 然后将我的 strings
复制到一个新的 ReadOnlyList
, 而 return 那?
此外,对象是否应该提供一种方法,return是对象的不可写克隆来解决这个问题?
您可以使用 getStrings return 一个不可修改的列表。
public List<String> getStrings() {
return Collections.unmodifiableList(this.strings);
}
Can I just trust that other classes won't try to edit my object through the getter?
没有
There's the option of cloning it (some classes may override the clone() method), but is this a good use for clone()? What are the best practices of cloning an object?
oracle 文档提供了一个建议的策略:
- Don't share references to the mutable objects. Never store references to external, mutable objects passed to the constructor; if necessary, create copies, and store references to the copies. Similarly, create copies of your internal mutable objects when necessary to avoid returning the originals in your methods. (https://docs.oracle.com/javase/tutorial/essential/concurrency/imstrat.html)
Is it worth it to create a custom class (called ReadOnlyList, for this example) that is only writeable in the constructor (like this), then copy my strings to a new ReadOnlyList, and return that?
在这种情况下不是(请参阅 Micky Loo 的回答)。但是在更特殊的情况下是的(如果你必须保证不变性并且不能复制对象)。
Also, should objects provide a method that returns a non-writable clone of the object to solve this?
您不能在 Java 中创建 const return 值。参见:Const return values in Java
我想制作一个 getter 不允许调用者编辑 returned 对象。
以 List
为例(尽管我希望答案也适用于任何其他类型),这是 returning 和编辑属性的常用方法:
class MyClass {
private List<String> strings;
// to get the whole object
public List<String> getStrings() {
return this.strings;
}
// to alter the object
public void addString(String newStr) {
this.strings.add(newStr);
}
//...
}
然而,这并不能阻止其他一些 class 这样做
myClassInstance.getStrings().add("that's a dumb implementation, bro");
这有点粗鲁,因为我为此特定目的创建了 addString()
。
我宁愿其他 classes 只使用 getStrings()
方法来读取,因为可能有类似的情况我不想实现 addString()
方法。在那种情况下,其他 classes 无论如何都可以通过 getter 编辑 strings
,但我仍然希望能够在 C
[=] 中私下编辑对象56=].
我知道如果属性是原始类型这不会有问题,因为它们直接保存在实例中,但对象是对内存的引用,所以任何 class 能够得到它的手如果对象类型允许,可以对这些引用进行编辑。
我可以相信其他 class 不会尝试通过 getter 编辑我的对象吗?
可以选择克隆它(某些 classes 可能会覆盖
clone()
method),但这对clone()
有用吗?克隆对象的最佳实践是什么?是否值得创建一个只能在构造函数中写入的自定义 class(在本例中称为
ReadOnlyList
)(如 this) , 然后将我的strings
复制到一个新的ReadOnlyList
, 而 return 那?此外,对象是否应该提供一种方法,return是对象的不可写克隆来解决这个问题?
您可以使用 getStrings return 一个不可修改的列表。
public List<String> getStrings() {
return Collections.unmodifiableList(this.strings);
}
Can I just trust that other classes won't try to edit my object through the getter?
没有
There's the option of cloning it (some classes may override the clone() method), but is this a good use for clone()? What are the best practices of cloning an object?
oracle 文档提供了一个建议的策略:
- Don't share references to the mutable objects. Never store references to external, mutable objects passed to the constructor; if necessary, create copies, and store references to the copies. Similarly, create copies of your internal mutable objects when necessary to avoid returning the originals in your methods. (https://docs.oracle.com/javase/tutorial/essential/concurrency/imstrat.html)
Is it worth it to create a custom class (called ReadOnlyList, for this example) that is only writeable in the constructor (like this), then copy my strings to a new ReadOnlyList, and return that?
在这种情况下不是(请参阅 Micky Loo 的回答)。但是在更特殊的情况下是的(如果你必须保证不变性并且不能复制对象)。
Also, should objects provide a method that returns a non-writable clone of the object to solve this?
您不能在 Java 中创建 const return 值。参见:Const return values in Java