在java.util.Collections中有一个内部类SynchronizedCollection 有两个构造函数。第一个采用集合,另一个采用集合和互斥。 前构造函数检查参数是否为空。但后来不要! 这是实施。
SynchronizedCollection(Collection<E> c) {
if (c==null)
throw new NullPointerException();
this.c = c;
mutex = this;
}
SynchronizedCollection(Collection<E> c, Object mutex) {
this.c = c;
this.mutex = mutex;
}
通过这个实现,我可以通过向第二个发送null来打破类的不变量 构造
我相信它应该是这样的:
SynchronizedCollection(Collection<E> c) {
this(c,this)
}
SynchronizedCollection(Collection<E> c, Object mutex) {
if (c==null)
throw new NullPointerException();
this.c = c;
this.mutex = mutex;
}
然而,我无法说服自己Josh Bloch和Neal Gafter看不到这一点。你能真的告诉我我错过了什么吗?
编辑:可能的攻击
Map<String, String> m = new Map<String, String>(){
@Override
public int size() {
// TODO Auto-generated method stub
return 0;
}
.
.
.
@Override
public Collection<String> values() {
return null;
}
};
Map<String, String> synchronizedMap = Collections.synchronizedMap(m);
Collection<String> values = synchronizedMap.values();
答案 0 :(得分:11)
当然这是一个错误。两个构造函数应该是一致的,要么两者都应该抛出异常,要么都不应该抛出。
这已在Java 8中修复。现在两个构造函数都将抛出异常:
SynchronizedCollection(Collection<E> c) {
this.c = Objects.requireNonNull(c);
mutex = this;
}
SynchronizedCollection(Collection<E> c, Object mutex) {
this.c = Objects.requireNonNull(c);
this.mutex = Objects.requireNonNull(mutex);
}
答案 1 :(得分:2)
这两个构造函数都受到包保护,只有第一个构造函数可以通过null
public
和synchronizedList()
synchronizedSet()
方法与Collections
参数一起使用}}。
其他构造函数在内部使用(在Collections
类中),并且在各种实现(调用代码)中第一个参数永远不能是null
,所以你不能破坏它。
您可以随时尝试在java.util
包中创建内容,但很可能会获得SecurityException
。