我正在阅读有关java中的可变/不可变类和复制构造函数,并偶然发现this example。
在复制构造函数中,他使用如下的getter:
(aGalaxy.aMass, aGalaxy.aName)
我的问题是,有没有其他原因,因为它是一个很好的编码实践,有人在复制构造函数中使用getter而不是只访问像{{1}}这样的字段。您也可以找到这样做的示例,但我的意思是它纯粹是一种编码风格,还是在复制构造函数中使用getter有潜在的好处?
答案 0 :(得分:1)
虽然在大多数情况下都是无害的,但是当子类选择覆盖你调用的getter时,这种做法会导致一些难以捕获的错误。
这是一个简单的例子:
class Base {
private final String name;
public String getName() {return name;}
public Base(String name) {
this.name = name;
}
public Base(Base b) {
this(b.getName());
}
}
class Derived extends Base {
public String getName() {
return "["+super.getName()+"]";
}
public Derived(String name) {
super(name);
}
public Derived(Derived d) {
this(d.getName());
}
}
请注意Derived
如何覆盖getName()
,因此Derived
的复制构造函数正在访问该名称的修改版本,从而导致出现问题:
Derived orig = new Derived("hello");
Derived copy = new Derived(orig);
System.out.println(orig.getName()); // Prints [hello]
System.out.println(copy.getName()); // Prints [[hello]]
最后一个印刷品的方括号加倍,因此副本不是真正的副本。
使用protected
个变量或让你的getter final
可以帮助你避免这个问题。
我认为这个问题的根本原因是让子类覆盖存储属性的getter,所以我更喜欢制作getter final
的方法。