2013-06-30 15 views
7

otrzymuję ostrzeżenie:Czy to powoduje zanieczyszczenie sterty przy użyciu varargs?

[niezaznaczone] Możliwe zanieczyszczenie sterty od typu parametryzowane vararg klasy

ale jestem pewien, czy będzie to rzeczywiście zanieczyszczają:

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

Oto pełne wdrożenie, jeśli jest to konieczne:

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

Jestem gotów na sugestie OT, aby to poprawić, ale pamiętajcie, że ta klasa jest niedokończona.

Odpowiedz

7

Ostrzeżenie dotyczące ogólnych varargs jest związane z dangers of generic arrays. Teoretycznie metoda może nadużywać macierzy kowariancji z przekazany w tablicy spowodować zanieczyszczenie sterty, na przykład:

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

Ale jest w porządku tak długo, jak realizacja metoda nic nie głupie jak to zrobić. Niektóre podstawowe środki ostrożności będą następujące:

  • Nie wykonuj żadnych zadań na eventTypes.
  • Nie należy zwracać ani w żaden inny sposób wystawiać poza metodą metody eventTypes.

Z Java 7, można opisywać metody z @SafeVarargs, które zasadniczo obiecuje kompilator, że tablice generyczne są w porządku (co oznacza, że ​​nie jest już na rozmówcy tłumić ostrzeżenie).

+1

Przykład oparty na moim kodzie wyraźnie pokazuje, jakie są pułapki. Sugerowane środki ostrożności pomagają mi zapobiegać błędom i że adnotacja oczyszcza IDE. Wszystko to z przydatnymi linkami. Świetna, zwarta odpowiedź, dzięki. – zsawyer

0

Należy uważać, aby treść metody rejestru nie powodowała wyjątków ClassCastException w czasie wykonywania z powodu nielegalnych argumentów. Jeśli masz pewność, że jest on obsługiwany, możesz bezpiecznie zignorować lub wyłączyć ostrzeżenie.

+0

-1: Nie ma to nic wspólnego z argumentami, które są przekazywane, ale z tym, jak metoda traktuje swój parametr varargs. –

2

Ilekroć masz generatory, które są generyczne (na przykład, lista uogólniona) masz możliwość zanieczyszczenia sterty. Na przykład:

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

W przykładzie masz Class<? extends Event> eventTypes... który pada ofiarą tego samego problemu:

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

    ... 
    ... 
} 

Java jest tylko ostrzeżeniem, że istnieje potencjalne rozwiązanie sterty zanieczyszczeń. W języku Java 7 ostrzeżenia są generowane również przy deklaracji metody, podczas gdy w poprzednich wersjach były tylko w witrynach wywołujących.

Jeśli masz pewność, że zanieczyszczenie sterty nie może wystąpić, możesz wyłączyć ostrzeżenie, używając adnotacji @SafeVarargs.

Powiązane problemy