2012-01-09 32 views
5

Mam metodę, która ma Set obiektów. Metoda, którą deleguje, wymaga, aby Set nie zawierał żadnych elementów zerowych. Chciałbym check the precondition, że Set nie zawiera żadnych elementów zerowych wcześniej, w metodzie przed delegacją. Oczywistym kod rób tak to:Dokładny sposób sprawdzenia, czy zestaw nie zawiera wartości pustej

public void scan(Set<PlugIn> plugIns) { 
    if (plugIns == null) { 
     throw new NullPointerException("plugIns"); 
    } else if (plugIns.contains(null)) { 
     throw new NullPointerException("plugIns null element"); 
    } 
    // Body 
} 

Ale to jest błędne, ponieważ Set.contains() może rzucić NullPointerException jeśli realizacja samaSet nie zezwala na elementy null. Catching następnie ignorowanie NullPointerException w tym przypadku będzie działać but would be inelegant. Czy istnieje dobry sposób na sprawdzenie tego warunku?


Czy w interfejsie Set występuje błąd projektowy? Jeśli implementacja Set nigdy nie może zawierać wartości null, dlaczego zamiast tego należy wymagać , aby zawsze zwracać false? Czy masz predykat isNullElementPermitted()?

+0

Jeśli masz konkretne wymaganie podobne do tego, podklasa 'Ustaw' i nie akceptuj' null' stawia. Poza tym nie używałbym tutaj słowa "else". –

Odpowiedz

4

Najprostszym sposobem jest wyliczenie zestawu i sprawdzenie wartości zerowych.

public void scan(Set<PlugIn> plugIns) { 
    if (plugIns == null) throw new NullPointerException("plugIns"); 
    for (PlugIn plugIn : plugIns) { 
    if (plugIn == null) throw new NullPointerException("plugIns null element"); 
    } 
} 
+0

Proste, ale 'O (N)' w złożoności, co jest złe dla sprawdzenia warunków wstępnych. – Raedwald

+0

Cytując inną: "Preoptymizacja jest źródłem wszelkiego zła". Czy na pewno jest to wąskie gardło wydajności? Biorąc pod uwagę to, co robisz, domyślam się, że w innym miejscu jest problem architektury. –

+0

Moją obawą jest * nie * przedwczesna optymalizacja. Schludny roztwór powinien być uniwersalny i racjonalnie wydajny. Za każdym razem, gdy ktoś używa 'HashSet' bez wcześniejszego mierzenia wydajności i uzyskuje korzyści z szybkiego' Set.contains() ', nie angażuje się w przedwczesną optymalizację. http://programmers.stackexchange.com/questions/79946/what-is-the-best-retort-to-premature-optimization-is-to-root-all-evil. – Raedwald

3

Tworzenie HashSet z plugIns i sprawdzić istnienie null

public void scan(Set<PlugIn> plugIns) { 
    if (plugIns == null) throw new NullPointerException("plugIns"); 
    Set<PlugIn> copy = new HashSet<PlugIn>(plugIns); 
    if (copy.contains(null)) { 
     throw new NullPointerException("null is not a valid plugin"); 
    } 
} 
+0

Prosty, ale 'O (N)' w złożoności i tworzy nowy obiekt, co jest złe dla sprawdzenia warunków wstępnych. – Raedwald

+1

Ile tysięcy razy na sekundę skanujesz w poszukiwaniu nowych wtyczek? ;) Z mojego doświadczenia wynika, że ​​kopiowanie lub tworzenie nowych kolekcji rzadko stanowi problem z wydajnością. Może powinieneś zapobiec dodawaniu 'null', skąd pochodzi' plugIns' (dla mnie brzmi to tak, jakbyś naprawiał czyjś błędny kod, chyba że istnieje uzasadniony powód istnienia wtyczki 'null') – Matt

+0

Nie robię tego w celu obejścia błędnego kodu. Chcę to zrobić, ponieważ lepiej wcześnie wykryć usterki. Wyobraźmy sobie, że była to metoda API: nie kontrolowalibyśmy kodu wywołującego, ale moglibyśmy chcieć zapewnić dobrą diagnostykę. – Raedwald

2

Wystarczy złapać NullPointerException jeśli rzucony i ignorować go:

public void scan(Set<PlugIn> plugIns) { 
    if (plugIns == null) { 
     throw new NullPointerException("plugIns"); 
    } 

    NullPointerException e = null; 
    try { 
     if (plugIns.contains(null)) { 
      // If thrown here, the catch would catch this NPE, so just create it 
      e = new NullPointerException("plugIns null element"); 
     } 
    } catch (NullPointerException ignore) { } 

    if (e != null) { 
     throw e; 
    } 
    // Body 
} 

Stwarza to jedynie niewielki narzut jeśli rzucone, ale jeśli nie korzystasz z wyjątku (zwłaszcza śledzenia strackowego), to jest całkiem lekki.

+0

Nie sądzisz, że Twoi kandydaci do NPE są bardziej kandydatami IllegalArgumentException? – Prakhar

Powiązane problemy