2011-12-19 7 views
18

Mam instrukcję przełącznika, jak pokazano poniżej. Zauważ, że nie ma przerwy. Findbugs zgłasza błąd tylko w drugim przypadku. Błąd jest następujący: Instrukcja switch znaleziona w przypadku, gdy jeden przypadek przechodzi do następnego przypadku.Przełącznik bez przerwy

switch(x) { 

    case 0: 
     // code 

    case 1: 
     // code 

    case 2: 
     // code 
} 
+3

co mówi komunikat o błędzie? –

+9

A problemem jest ...? – fge

+0

Czy na pewno nie jest to ostrzeżenie, a nie błąd? – xagyg

Odpowiedz

2

Bez przerwy wpadną chociaż do siebie, więc jeśli x == 0 pójdziesz przez cały kod w każdym bloku case. Findbugs może być błędne w związku z błędem, lub może to być stan błędu bez przerwy, tj. Coś w case 0 powoduje, że coś w case 1 pęka.

Bez dokładnego kodu i błędu nie mogę pomóc dalej. Czy brak przerw jest celowy?

60

Findbugs sygnalizuje, że przechodzenie z jednego case do następnego nie jest dobrym pomysłem, jeśli w pierwszym jest jakikolwiek kod (chociaż czasami można go wykorzystać do dobrego efektu). Więc gdy widzi drugi case i nie break, zgłasza błąd.

Tak na przykład:

switch (foo) { 
    case 0: 
     doSomething(); 
    case 1: 
     doSomethingElse(); 
    default: 
     doSomeOtherThing(); 
} 

To jest całkowicie poprawny Java, ale to chyba nie robi tego, co autor ma: Jeśli foo jest 0, wszystkie trzy funkcji doSomething, doSomethingElse i doSomeOtherThing uruchom (w tej kolejności). Jeśli foo jest 1, działają tylko doSomethingElse i doSomeOtherThing. Jeśli foo ma jakąkolwiek inną wartość, działa tylko doSomeOtherThing.

W przeciwieństwie:

switch (foo) { 
    case 0: 
     doSomething(); 
     break; 
    case 1: 
     doSomethingElse(); 
     break; 
    default: 
     doSomeOtherThing(); 
     break; 
} 

Tutaj tylko jedna z funkcji będzie działać, w zależności od wartości foo.

Ponieważ jest to typowy błąd kodowania, aby zapomnieć o break, narzędzia takie jak Findbugs podnoszą to za Ciebie.

Jest częstym use-case gdzie masz kilka case oświadczenia w jednym rzędzie z nie kod interwencyjnym:

switch (foo) { 
    case 0: 
    case 1: 
     doSomething(); 
     break; 
    case 2: 
     doSomethingElse(); 
     break; 
    default: 
     doSomeOtherThing(); 
     break; 
} 

Nie chcemy zadzwonić doSomething jeśli foo jest 0lub1. Większość narzędzi nie sygnalizuje tego jako możliwego błędu kodowania, ponieważ nie ma kodu w case 0 przed case 1 i jest to dość powszechny wzorzec.

+1

Czy 'break' jest naprawdę konieczne na końcu? – kcpr

+2

@kcpr: Ściśle mówiąc, nie potrzebujesz "break;" w ostatnim przypadku przełącznika ('default' w powyższym przykładzie). Ale wolę spójność. To czysto kwestia stylu, ten sam kod bajtowy jest produkowany w obu kierunkach. (Nie jest to oczywiście prawdą, jeśli zostawisz coś innego * 'break *).) –

+0

To jest bardzo dobry opis typowego problemu i jak działa przełącznik, ale tak naprawdę nie odpowiada na pytanie OP - chociaż, ściśle rzecz biorąc, PO faktycznie nie przedstawił pytania ... – Tasgall

3

Przełączniki typu fall-throughs należą do kategorii "Znajdź kod". Sądzę, że ogranicza on tylko pierwsze wystąpienie fall-through w instrukcji switch, aby zmniejszyć liczbę komunikatów o błędach.

4

Napisałem je jako komentarze, ale nie są one widoczne. Zamieniam je w odpowiedź. Jest to faktycznie rozszerzenie do T.J.Crowder's answer.

Możesz znaleźć pokrewną regułę, która powoduje, że Findbugs zgłasza błąd here.

Możesz zapobiec wyświetlaniu tego typu błędów przez Findbugs, tworząc plik xml o następującej treści, na przykład filter.xml i uruchamiając narzędzie z opcją -exclude filter.xml. Zobacz filters on Findbugs.

<FindBugsFilter> 
    <Match> 
    <Bug category="PERFORMANCE" /> 
    </Match> 
</FindBugsFilter> 
+0

W przepełnieniu stosu jest całkowicie dopuszczalne edytowanie cudzej odpowiedzi w celu dodania użytecznych informacji (takich jak powyższe). Idź po to! –

+1

@ T.J.Crowder niestety moje poprawki zostały odrzucone, musiałem cofnąć odpowiedź. Dzięki za sugestię. – melihcelik

+0

Podejrzewam, że faktyczna zasada była bardziej ogólna ['SF_SWITCH_FALLTHROHH'] (http: // findbugs.sourceforge.net/bugDescriptions.html#SF_SWITCH_FALLTHROHH). 'SF_DEAD_STORE_DUE_TO_SWITCH_FALLTHROUGH' oznacza," nie tylko był fall-through, ale to clobbered coś, co próbował zapisać w poprzednim przypadku ". Prawdopodobnie jest to prawdopodobnie błąd, więc znacznie bardziej niechętnie wyłączałbym regułę "DEAD_STORE" niż regułę "FALLTHROUGH". –

2

Zazwyczaj narzędzia analizy błędów nie podoba fallthrough w kodzie, ponieważ w większości przypadków, użytkownik po prostu zapomniał napisać przerwę.

ja nie wiem, czy istnieje sposób, aby specjalnie wyłączyć ostrzeżenie z FindBugs ale Checkstyle narzędzia rozpoznać specjalne komentarze, takie jak /* fallthrough */ zakładać, że użytkownik naprawdę chce następujący kod do wykonania. Umieszczenie tego rodzaju komentarza poprawia również czytelność. http://checkstyle.sourceforge.net/config_coding.html#FallThrough

Konwencja dotycząca kodu Java wspomina również o używaniu komentarza dotyczącego odrzucania. http://www.oracle.com/technetwork/java/javase/documentation/codeconventions-142311.html

0

Jeśli twoje przypadki nie mają przerwy, po wywołaniu sprawy przełącznik przechodzi przez wszystkie przypadki, aż znajdzie przerwę lub koniec skrzynek. Jeśli masz domyślny przypadek, zostanie wywołany, jeśli twoja wartość przełącznika w tym przypadku foo nie pasuje do żadnych innych przypadków.