Search code examples
javaclassencapsulation

Why can I set the value of a private class attribute with getter in Java?


I'm new to Java and I wonder why it is possible to set the value of a private attribute this way, without using a setter ? :

class Example {
   private int[] thing;
   public void initialize() {
       thing = new int[10];
   }
   public int[] getThing() { 
       return thing;
   }
}
class myclass {
   public static void main(String args[]) {
       Example e = new Example();
       e.initialize();
       e.getThing()[0] = 1;
       System.out.println(e.getThing()[0]) // value is still 1...
}

I really do not understand why this is legal...

Edit: I expected e.getThing() to return the value of thing not a reference to thing and even if it was the case, as "thing" is private I thought I wont be able to modify it directly.


Solution

  • You're exposing the reference to an array from the getter, and the array contents themselves are mutable i.e. you can change them. So in your example above you return a reference to the array held by the private variable in the class, you amend that array, and that change will be visible via the getter going forwards because it always returns that modified array.

    To avoid this, what you could do is either:

    1. return a read-only view of the collection via your getter. This could be fast, but if the parent object changes the array contents under you whilst you're (say) iterating over it, then this could be confusing
    2. return a defensive copy via your getter. This would mean returning a new array copy per call, and this wouldn't change under you, but you pay a cost in copying it for each call

    In your specific example above, you could create a read-only collection within your initialize() method, and then you're not going to have this issue.

    I think you need to be clear re. private (i.e. the reference variable is not available outside the class) and mutable (the object you're returning can change). These are two very different concepts.