In C++, I can define an accessor member function that returns the value of (or reference to) a private data member, such that the caller cannot modify that private
You could return a copy of the member, thus changes will not be reflected in the object the private reference points to. With primitives, of course, this problem doesn't exist.
Be mindful of memory usage, however! This might not be the right solution for all situations. In that case, an immutable object as suggested in another answer might be the way to go.
There's no equivalent to the C const
"type modifier" in Java (sadly).
The closest you can get is to return an immutable object or an immutable wrapper around a mutable object.
Immutability is not a language feature of Java, however, so you'll have to rely on Libraries.
Examples of immutable objects are:
Integer
, Character
, ..String
File
URL
Commonly used immutable wrapper (i.e. wrappers around mutable types that prevent mutation) are those returned by the Collecton.unmodifiable*() methods.
When you do something like this:
Object2 obj2 = obj1.getObj2();
obj2 = new Object2();
The original private member (obj1.obj2) remains as it were before (just to be sure that you grasped that concept). You can just omit the setter to obj2 so that the inner field cannot de changed.
If you want Object2 fields to be immutable you will need to apply the same pattern (private fields, no setters).
This answer your question?
I don't think there is a way to that in Java for non primitive objects (you're always passing around references to such objects). The closest you could do would be to return a copy of the object (using clone or something like that) ; but that would not be very idiomatic Java.
I you want to give access only to the 'visible' part of a member object, what you could do is create an interface with the visible part, and return this interface. For example :
public interface Bar {
public int getBing();
}
public class BarImpl implements Bar {
private int bing;
public int getBing() {
return bing;
}
public void setBing(int bing) {
this.bing = bing;
}
}
public class Foo {
private BarImpl bar;
public Bar getNonModifiableBar() {
return bar; // Caller won't be able to change the bing value, only read it.
}
}
It's up to the returned object to prevent modification. Java doesn't provide declarative/compile-time checking of unmodifiable objects except to the extent that the type lacks mutators.
There is some support in the JDK: methods like Collection.unmodifiableCollection will create an object that will throw runtime exceptions if the client calls collection mutator methods.
If you're truly motivated, you can get compile-time checks by defining read-only interfaces (or classes) that only expose/implement accessor methods on your own. Keep in mind that merely declaring that a method returns a read-only interface will not prevent runtime modification if the client uses introspection and the object provides mutators (that don't throw UnsupportedOperationException).
You either return an immutable object, or return a copy of the private instance variable. This way, the object's internal state is "protected" from modification, i.e.:
private MyMutableObject mutable = ...
public MyMutableObject getMutableObject() {
return new MyMutableObject(this.mutable);
}
`