Reputation: 455
I want to make a getter that doesn't allow the caller to edit the returned object.
Using a List
as an example (though I would like the answer to apply to any other type as well), this is the usual approach for returning and for editing an attribute:
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);
}
//...
}
However, this doesn't prevent that some other class from doing this
myClassInstance.getStrings().add("that's a dumb implementation, bro");
and that would be kind of rude since I created addString()
for that specific purpose.
I would rather if other classes would only use the getStrings()
method for reading, because there might be a similar case where I don't want to implement the addString()
method. In that situation, other classes are able to edit strings
anyway through the getter, but I still want to be able to edit the object privately in the C
class.
I know this wouldn't be a problem if the attribute was a primitive type since those are saved directly in the instance, but objects are references to memory, so any class that's able to get its hands on those references can edit it if the object type allows that.
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?
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?
Also, should objects provide a method that returns a non-writeable clone of the object to solve this?
Upvotes: 0
Views: 286
Reputation: 509
Can I just trust that other classes won't try to edit my object through the getter?
No.
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?
The oracle docs provide a proposed strategy:
- 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?
In this case not (see Micky Loo's answer). However in a more special case yes (if you have to guarantee immutableness and can not copy the object).
Also, should objects provide a method that returns a non-writable clone of the object to solve this?
You can not create a const return value in Java. see: Const return values in Java
Upvotes: 0
Reputation: 1493
You can have getStrings return an unmodifiable list.
public List<String> getStrings() {
return Collections.unmodifiableList(this.strings);
}
Upvotes: 2