2011-01-20 63 views
2

我完全被這個弄糊塗了。我正在運行一整套完整的單元測試。以下是有關共享代碼被使用一些JUnit測試:什麼會導致HashMap containsKey()失敗並以String爲關鍵字?

private static Map<String, JAXBContext> jaxbContexts = 
          new HashMap<String, JAXBContext>(); 

private synchronized JAXBContext getJAXBContext(Class clazz) throws JAXBException { 
    JAXBContext context = null; 
    if (jaxbContexts.containsKey(clazz.getName())) { 
     context = jaxbContexts.get(clazz.getName()); 
    } else { 
     context = JAXBContext.newInstance(clazz); 
     System.out.println("Created new context for '" + clazz.getName() + "'"); 
     jaxbContexts.put(clazz.getName(), context); 
    } 
    return context; 
} 

從JUnit的運行輸出控制檯包括以下兩個連續的條目:

Created new context for 'com.somecompany.xmlschema.providepensionpaymentinfo.Interface' 
Created new context for 'com.somecompany.xmlschema.providepensionpaymentinfo.Interface' 

我缺少什麼?爲什麼jaxbContexts.containsKey()在這種情況下不能用於基於字符串的鍵,與JUnit執行期間的其他46次不同?我們並不是在同時運行我們的測試,但是如果這有所作爲,我們會使用Aspects。

+0

您確定這兩行之間沒有停止/啓動JVM嗎? – Pointy 2011-01-20 14:20:59

回答

3

調試和驗證包含此getJAXBContext()方法的類實例化只有一次(通過檢查它在調試模式相同的內存ID爲每次調用它)。如果它是不同的實例,那麼synchronized關鍵字將鎖定在不同的鎖上,它們將使用不同的地圖。

+0

謝謝。調試確實驗證了(至少)有兩個靜態jaxbContexts實例。此代碼位於具有多個具體實現的抽象基類中。每個子類都有一個這個字段的靜態實例嗎? – 2011-01-20 14:58:58

1

就我個人而言,我不打擾containsKey。

String name = clazz.getName(); 
context = jaxbContexts.get(name); 
if (context == null) { 
    context = JAXBContext.newInstance(clazz); 
    System.out.println("Created new context for '" + name + "'"); 
    jaxbContexts.put(name, context); 
} 
+0

好的,但這並不影響這個結果,它暗示containsKey正在工作,而我的問題其實在於jaxbContexts的多個靜態實例。 – 2011-01-20 14:57:18

+0

是的,我知道這實際上並沒有解決問題。這就是爲什麼我投了@傑弗裏的答案。 – 2011-01-20 15:05:28

0

除了比賽......但是你說你不併行運行的東西...

無論如何,我會叫context = jaxbContexts.get(clazz.getName())和測試contextnull

啊,而且使用的類本身作爲重點,因爲不止一個類可以有相同的名稱(認爲的類加載器)

1

有一定沒有什麼特別的包含字符串作爲鍵地圖。只需將替換爲println,您就會看到發生了什麼。你可能正在創建持有地圖的類的兩個實例,或者其他任何東西。

-1

該地圖可以是Map<Class, JAXBContext>而不是Map<String, JAXBContext>以方便使用。

相關問題