2013-06-30 17 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注释来禁止警告。

相关问题