这是Java SynchronizedCollection类中的错误吗?

时间:2013-09-29 15:59:59

标签: java collections

在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();

2 个答案:

答案 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 publicsynchronizedList() synchronizedSet()方法与Collections参数一起使用}}。

其他构造函数在内部使用(在Collections类中),并且在各种实现(调用代码)中第一个参数永远不能是null,所以你不能破坏它。

您可以随时尝试在java.util包中创建内容,但很可能会获得SecurityException