2013-09-29 41 views
7

有一個內部類SynchronizedCollection - 內部java.util.Collections 有兩個構造函數。第一個需要收集,另一個需要收集和互斥。 前構造函數檢查不爲null的參數。但後來不! 這裏是實現。這是Java 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; 
} 

這個實現,我可以打破階級通過發送空至第二 構造不變。

我相信它應該是這樣的:

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; 
} 

但是我無法說服自己喬希布洛赫和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(); 

回答

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); 
} 
2

那些構造的兩者都是封裝保護,只有第一個可能被通過的CollectionspublicsynchronizedList()synchronizedSet()方法null參數使用。

其他構造函數在內部使用(在Collections類中),並且第一個參數在各種實現(調用代碼)中永遠不會是null,因此您無法將其分解。

你總是可以嘗試在java.util包中創建一些東西,但很可能會得到一個SecurityException

+2

我是否可以extends Map接口的替代值()方法,而又不會讓我在執行java.util包返回null!該對象返回的值()方法發送到第二個構造函數 - 請參閱Collections.synchronizedMap()和Boom! –

+0

參見我的編輯註釋 –

+1

@MortezaAdi公平地說,這可能被認爲是濫用Map.values()的合約,而該合約不明確地允許這種行爲。 (它並不禁止它,但是:你**是否曾經** null-檢查來自'entrySet()','keySet()'或'values()'的返回值?你見過其他人嗎?所以?)我會告訴你,這個類缺乏健壯性,但是如果沒有實際濫用API,就沒有辦法打破它。我同意Sotirios的觀點,如果你能以某種方式導致第三方代碼崩潰,那麼這將是一個更大的問題。 – millimoose