这可能是一个常见的问题,但我找不到很好的解释.我想了解encapsulation of reference variables中Java.
在以下代码中:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
输出: bobfred
起初我认为制作我们的领域private并提供一种getter方法,这是一种很好的封装技术.但是当我仔细观察它时,我看到当我调用时getName(),我确实会返回一个副本,就像Java一样.但是,我没有返回该StringBuilder对象的副本.我正在返回一个指向唯一StringBuilder对象的引用变量的副本.所以,在getName()返回的点上,我有一个StringBuilder对象和两个指向它的引用变量(s和s2).
有什么技术可以很好地封装?代码示例预期的一个很好的解释:).提前致谢.
我能想到两种基本方法.
第一种是只返回不可变的值.然后呼叫者可以按照自己的意愿行事,而不会冒任何对象的完整性.在您的情况下,不可变类型将是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"
}
}
Run Code Online (Sandbox Code Playgroud)
注意:如果s需要是a StringBuilder,您可以退货s.toString().
另一种选择是返回一个可变值,但在getter中创建一个防御性副本.换句话说,返回带有重复数据的单独引用:
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"
}
}
Run Code Online (Sandbox Code Playgroud)