[英]clone() non final classes
As per Josh Bloch's Effective java :- 根据Josh Bloch的有效java: -
do not use the clone method to make a defensive copy of a parameter whose type is subclassable by untrusted parties.
不要使用clone方法制作一个参数的防御性副本,该参数的类型可由不信任方进行子类化。
Now taking a expert from his book only:- 现在只从他的书中找专家: -
public final class Period {
private final Date start;
private final Date end;
/**
* @param start the beginning of the period
* @param end the end of the period; must not precede start
* @throws IllegalArgumentException if start is after end
* @throws NullPointerException if start or end is null
*/
public Period(Date start, Date end) {
if (start.compareTo(end) > 0)
throw new IllegalArgumentException(
start + " after " + end);
this.start = start;
this.end = end;
}
public Date start() {
return start;
}
public Date end() {
return end;
}
... // Remainder omitted
} }
I do not get what wrong would happen if I modify a accesor method to return a copy of date object using clone function instead of copy using constructor like this :- 如果我修改一个accesor方法使用clone函数返回日期对象的副本而不是使用像这样的构造函数复制,我不会得到什么错误: -
public Date start() {
return start.clone();
}
instead of 代替
public Date start() {
return new Date(start.getTime());
}
How possibly can a instance of malicious subclass be returned? 怎么可能返回恶意子类的实例?
Take the java.util.Date
class which provides a defensive copy in its clone()
method but which is also not final. 以
java.util.Date
类为例,该类在其clone()
方法中提供防御性副本,但也不是最终的。
Suppose I subclass Date
and I override the clone()
method. 假设我是
Date
子类,我重写了clone()
方法。
Now, at runtime, if I receive an instance of this subclass, clone()
of Date is not used anylonger. 现在,在运行时,如果我收到此子类的实例,则不再使用Date的
clone()
。 So, I am not sure that the implementation of the child class makes still a defensive copy as the original. 所以,我不确定子类的实现是否仍然是原始的防御性副本。
This : 这个 :
public Date start() {
return start.clone();
}
will not be a defensive copy if a subclass overrides clone()
like that : 如果子类重写
clone()
,则不会是防御性副本:
@Override
public Object clone() {
return this;
}
Instance of malicious subclass be returned for the accessor method. 为访问器方法返回恶意子类的实例。 Quoting from the same chapter -
引用同一章 -
In the accessors, unlike the constructor, it would be permissible to use the clone method to make the defensive copies.
在访问器中,与构造函数不同,允许使用克隆方法来制作防御性副本。 This is so because we know that class of
Period
's internalDate
objects isjava.util.Date
, and not some potentially untrusted subclass.这是因为我们知道
Period
的内部Date
对象的类是java.util.Date
,而不是一些可能不受信任的子类。
Expanding a bit on 扩大一点
do not use the clone method to make a defensive copy of a parameter whose type is subclassable by untrusted parties.
不要使用clone方法制作一个参数的防御性副本,该参数的类型可由不信任方进行子类化。
Since Date
is not final, it can be subclassed to change its behavior so the clone method of Date
could very well return an instance of a malicious subclass. 由于
Date
不是final,因此可以将其子类化以更改其行为,因此Date
的clone方法可以很好地返回恶意子类的实例。
Example 例
public class TestNonFinalCloneIssue {
public static void main(String[] args) {
NonFinalDate start = new NonFinalDate();
NonFinalDate end = new NonFinalDate();
Period p = new Period(start, end);
// We are completely obvious to the fact that copies of our data
// exists in another malicious class
System.out.println("Secretly copied data - " + NonFinalDate.MaliciousDate.getListOfInstances());
}
}
final class Period {
private final NonFinalDate start;
private final NonFinalDate end;
public Period(NonFinalDate start, NonFinalDate end){
NonFinalDate s = start.clone();
NonFinalDate e = end.clone();
if (s.compareTo(e) > 0){
throw new IllegalStateException(start + " after " + end);
}
this.start = s;
this.end = e;
}
}
class NonFinalDate extends Date{
@Override
public NonFinalDate clone(){
// NonFinalDate returning a malicious subclass (subclassing possible only because NonFinalDate is not final)
return new MaliciousDate(this);
}
static class MaliciousDate extends NonFinalDate {
private static List<NonFinalDate> listOfInstances = new ArrayList<>();
public MaliciousDate(NonFinalDate date){
// Secretly making copies of the data
listOfInstances.add(date);
}
public static List<NonFinalDate> getListOfInstances() {
return listOfInstances;
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.