复制构造函数访问其类的字段?

时间:2016-09-23 02:31:39

标签: java copy-constructor

我正在阅读有关java中的可变/不可变类和复制构造函数,并偶然发现this example

在复制构造函数中,他使用如下的getter:

(aGalaxy.aMass, aGalaxy.aName)

我的问题是,有没有其他原因,因为它是一个很好的编码实践,有人在复制构造函数中使用getter而不是只访问像{{1}}这样的字段。您也可以找到这样做的示例,但我的意思是它纯粹是一种编码风格,还是在复制构造函数中使用getter有潜在的好处?

1 个答案:

答案 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的方法。

Demo.