It may be a common question but I couldn't find nice explanation for it. I am trying to understand the encapsulation of reference variables
in Java
.
In the below code:
class Special {
private StringBuilder s = new StringBuilder("bob");
StringBuilder getName() { return s; }
void printName() { System.out.println(s); }
}
public class TestSpecial {
public static void main (String[] args ) {
Special sp = new Special();
StringBuilder s2 = sp.getName();
s2.append("fred");
sp.printName();
}
}
Output: bobfred
At first I thought making our field private
and providing a getter
method, it's a good encapsulation technique. But when I took closer look on it, I saw that when I invoke getName()
, I do in fact return a copy, just like Java always does. But, I am not returning a copy of the StringBuilder
object. I am returning a copy of the reference variable that point to the one and only StringBuilder
object. So, at the point that getName()
returns, I have one StringBuilder
object and two reference variables pointing to it ( s and s2).
What are the techniques to make it well encapsulated?? A good explanation with code example expected :) . Thanks in advance.
There are two basic approaches I can think of.
The first is to only return immutable values. The caller can then do what he wants without risking the integrity of your object. In your case, the immutable type would be String
:
class Special {
private String s = "bob";
String getName() { return s; }
void printName() { System.out.println(s); }
}
public class TestSpecial {
public static void main (String[] args ) {
Special sp = new Special();
String s2 = sp.getName();
s2 += "fred";
// Alternatively: StringBuilder s2 = new StringBuilder(sp.getName()).append("fred");
sp.printName(); // prints "bob"
}
}
Note: If s
needs to be a StringBuilder
, you can return s.toString()
.
The other option is to return a mutable value, but create a defensive copy in your getter. In other words, return a separate reference with duplicate data:
class Special {
private StringBuilder s = new StringBuilder("bob");
StringBuilder getName() { return new StringBuilder(s); } // return a copy of s
void printName() { System.out.println(s); }
}
public class TestSpecial {
public static void main (String[] args ) {
Special sp = new Special();
StringBuilder s2 = sp.getName();
s2.append("fred");
sp.printName(); // prints "bob"
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With