Java:为什么不应该将 clone() 用于防御性复制?

Kyl*_*yle 6 java effective-java

在 Effective Java(第 7 章)中,它说

还要注意,我们没有使用 Date 的 clone 方法来制作防御性副本。因为 Date 是非最终的,所以 clone 方法不能保证返回一个类是 java.util.Date 的对象:它可能返回一个专为恶意恶作剧设计的不受信任子类的实例。例如,这样的子类可以在创建时在私有静态列表中记录对每个实例的引用,并允许攻击者访问该列表。这将使攻击者可以自由支配所有实例。为防止此类攻击,请勿使用 clone 方法制作类型可被不受信任方子类化的参数的防御性副本。

我不太明白它的解释。为什么 clone() 不返回 Date 对象?实例怎么可能是不受信任的子类?

chr*_*ke- 5

clone()由于多种原因,人们普遍认为这是一次失败的实验。在这种情况下,传入 a 的人Date可能传入了 an EvilDate extends Date,其clone()方法偷偷地返回了其他人仍可变的副本。


egr*_*cer 5

考虑这段代码:

public class MaliciousDate extends Date { /** malicious code here **/ }

public class SomeClass {
    public static void main(String[] args) {
        MaliciousDate someDate = new MaliciousDate();
        Date copyOfMaliciousDate = someDate;
        Date anotherDate = copyOfMaliciousDate.clone();
    }
}
Run Code Online (Sandbox Code Playgroud)

由于copyOfMaliciousDateis 的类型Date,您可以调用clone()它,它将返回一个Date对象,但是调用cloneon会执行类copyOfMaliciousDate中编写的代码,因为存储在 中的实例是.MaliciousDateclone()copyOfMaliciousDateMaliciousDate