Search code examples
javaencapsulation

Publication/Escape and Encapsulation in Java


I'm reading the "Java Concurrency in Practice" book and there is a part that I don't quite understand. I know is an old book, and probably is the reason why there is no mention of my doubt.

In the "Sharing object" chapter there is a the section called "Publication and escape":

Publishing an object means making it available to code outside of its current scope, such as by storing a reference to it where other code can find it, returning it from a nonprivate method, or passing it to a method in another class ...

An object that is published when it should not have been is said to have escaped.

And there is an example:

class UnsafeStates
{
   private String[] states = new String []
   {"AK", "AL" ....};

   public String [] getStates(){return states;}
}

Publishing states in this way is problematic because any caller can modify its contents. In this case, the states array has escaped its intend scope, because what was supposed to be private state has been effectively made public.

And is specified to don't do never in this way.

I suddendly thought about the encapsulation concept where, basically, say to do exactly this.

I misunderstood the concepts or what?


Solution

  • The problem is this method:

    public String [] getStates(){return states;}
    

    Return your reference to states array.

    Even though you declare states as private but if you get it via getStates() method, you still can modify the states variable:

    UnsafeStates us = new UnsafeStates();
    String[] copyStates = us.getStates();
    copyStates[0] = "You don't know"; // Here the change to `copyStates` also affect the `states` variable since they're both reference to the same array.
    

    Normally, for objects and array properties, you often return a deep copy of that properties to prevent modify internal properties.

    Ex: For array:

    String[] copied = new String[states.length];
    System.arraycopy(states, 0, copied, 0, states.length);
    return copied;
    

    For List:

    return Collections.unmodifiableList(internalList);
    

    For Object:

    return internalObject.clone(); // Require deep clone