2013-06-30 46 views
7

我收到警告:這是否會導致可變參數堆的污染?

[選中]可能堆從參數可變參數的類型類污染

但我不確定是否將實際污染:

public void register(EventListener listener, Class<? extends Event>... eventTypes) {} 

這裏必要時完整實施:

public class EventDispatcher { 

    public static ConcurrentLinkedQueue<Event> eventQueue; 
    public static ConcurrentHashMap<Class<? extends Event>, CopyOnWriteArrayList<EventListener>> eventsListenerMap = 
      new ConcurrentHashMap<>(); 

    public static void register(EventListener listener, Class<? extends Event>... eventTypes) { 
     for (Class<? extends Event> eventType : eventTypes) { 
      if (eventsListenerMap.containsKey(eventType)) { 
       eventsListenerMap.get(eventType).addIfAbsent(listener); 
      } else { 
       CopyOnWriteArrayList<EventListener> initializingListeners = 
         new CopyOnWriteArrayList<>(); 
       initializingListeners.add(listener); 
       eventsListenerMap.put(eventType, initializingListeners); 
      } 
     } 
    } 
} 

爲了改善這一點,我也爲OT提出了一些建議,但請記住,這個課程還沒有完成。

回答

7

有關泛型可變參數的警告與dangers of generic arrays有關。理論上,該方法可能濫用陣列協方差與陣列傳遞造成堆污染,例如:

Class<?>[] eventTypesWithWidenedType = eventTypes; 
eventTypesWithWidenedType[0] = String.class; 
Class<? extends Event> eventType = eventTypes[0]; // liar! 

但由於該方法實現不做傻事喜歡它的罰款,只要。一些基本的預防措施是:

  • 不要對eventTypes進行任何分配。
  • 不要在方法之外返回或以其他方式暴露eventTypes

使用Java 7,您可以用@SafeVarargs,基本承諾編譯器通用陣列好(這意味着它不再呼叫者相應的警告)標註的方法。

+1

基於我的代碼的例子明確了什麼是陷阱。建議的預防措施可幫助我防止出現錯誤,並且該註釋會清除IDE。所有與有用的鏈接。好,緊湊的答案,謝謝。 – zsawyer

0

您需要注意,由於非法參數,註冊方法的主體不會在運行時拋出ClassCastException。如果你確定它被處理,那麼你可以放心地忽略或壓制警告。

+0

-1:這與傳入的參數沒有任何關係,但與方法如何處理其可變參數參數有關。 –

2

每當你有通用化的可變參數(例如,一個通用列表)時,你就有可能造成堆污染。例如:

public void doSomethingWithStrings(List<String>... strings) { 
    Object[] objectArray = strings; //Valid because Object is a valid supertype 
    objectArray[0] = Arrays.asList(new Integer(42)); //Heap pollution 

    String string = strings[0].get(0); //Oops! ClassCastException! 
} 

在你的榜樣,你有Class<? extends Event> eventTypes...其獵物下降到了同樣的問題:

public static void register(EventListener listener, Class<? extends Event>... eventTypes) { 
    Object[] objectArray = eventTypes; 
    objectArray[0] = String.class; //Heap pollution 

    ... 
    ... 
} 

的Java只是警告你,有一個潛在的堆污染的解決方案。在Java 7中,警告是在該方法的聲明中生成的,而在以前的版本中則只在呼叫站點中生成。

如果您確定不會發生堆污染,則可以使用@SafeVarargs註釋來禁止警告。

相關問題