2011-12-19 3 views
18

Ho alcune istruzioni sull'interruttore come mostrato di seguito. Si noti che non c'è alcuna interruzione. Findbugs sta segnalando un errore solo nella seconda dichiarazione del caso. L'errore è: l'istruzione switch è stata individuata dove un caso passa al caso successivo.Interruttore senza interruzione

switch(x) { 

    case 0: 
     // code 

    case 1: 
     // code 

    case 2: 
     // code 
} 
+3

cosa dice il messaggio di errore? –

+9

E il problema è ...? – fge

+0

Sei sicuro che non sia un avvertimento piuttosto che un errore? – xagyg

risposta

2

Senza la pausa cadranno anche se le une nelle altre, quindi se x == 0 andrai attraverso tutto il codice in ogni blocco istruzione case. Findbug potrebbe essere sbagliato sull'errore o potrebbe essere una condizione di errore senza interruzione, ad esempio qualcosa in case 0 causa un'interruzione di qualcosa in case 1.

Senza il codice esatto e l'errore non posso davvero aiutare ulteriormente. La mancanza di pause è intenzionale?

60

Findbugs segnala che il passaggio da uno case a quello successivo non è generalmente una buona idea se c'è un codice nel primo (anche se a volte può essere utilizzato con buoni risultati). Quindi, quando vede il secondo case e n. break, segnala l'errore.

Così, per esempio:

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

Ciò è perfettamente valido Java, ma probabilmente non fa quello che l'autore intendeva: se foo è 0, tutti e tre le funzioni doSomething, doSomethingElse, e doSomeOtherThing run (in questo ordine). Se foo è 1, eseguire solo doSomethingElse e doSomeOtherThing. Se foo è un qualsiasi altro valore, viene eseguito solo doSomeOtherThing.

Al contrario:

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

Qui, una sola delle funzioni verrà eseguito, a seconda del valore di foo.

Poiché si tratta di un errore di codifica comune per dimenticare lo break, gli strumenti come Findbugs lo segnalano.

C'è un caso d'uso comune in cui si dispone di più case dichiarazioni di fila con senza intervenendo codice:

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

Lì vogliamo chiamare doSomething se foo è 0o1. La maggior parte degli strumenti non contrassegnerà questo come un possibile errore di codifica, perché non è presente alcun codice nello case 0 precedente allo case 1 e questo è uno schema abbastanza comune.

+1

Alla fine è necessario 'break'? – kcpr

+2

@kcpr: Strettamente parlando, non è necessario un 'break;' sull'ultimo caso di un interruttore ('default' in precedenza). Ma preferisco la coerenza. È puramente una questione di stile, lo stesso bytecode è prodotto in entrambi i modi. (Questo non è, ovviamente, vero se si interrompe qualsiasi * altra * interruzione; '.) –

+0

Questa è una descrizione molto buona del problema comune e di come funziona lo switch, ma in realtà non risponde alla domanda dell'OP - anche se, in senso stretto, l'OP non ha presentato una domanda ... – Tasgall

3

Gli interruttori passano sotto la categoria Findbugs di "codice dodgy". Penso che contrassegna solo la prima occorrenza di un fall-through in un'istruzione switch per ridurre il numero di messaggi di errore.

4

Ho scritto questi come commenti ma non è visibile. Li sto trasformando in una risposta. Questa è in realtà un'estensione a T.J.Crowder's answer.

È possibile trovare la regola correlata che fa sì che Findbugs segnali un errore here.

È possibile impedire a Findbug di segnalare questo tipo di errori creando un file xml con il seguente contenuto, ad esempio filter.xml ed eseguendo lo strumento con l'opzione -exclude filter.xml. Vedi filters on Findbugs.

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

In overflow dello stack, in realtà è perfettamente accettabile modificare la risposta di qualcun altro per aggiungere informazioni utili (come sopra). Fallo! –

+1

@ T.J.Crowder purtroppo le mie modifiche sono state respinte, ho dovuto annullare la mia risposta. Grazie comunque per il suggerimento. – melihcelik

+0

Sospetto che la regola attuale fosse la più generale ['SF_SWITCH_FALLTHROUGH'] (http: // findbugs.sourceforge.net/bugDescriptions.html#SF_SWITCH_FALLTHROUGH). 'SF_DEAD_STORE_DUE_TO_SWITCH_FALLTHROUGH' significa che" non solo c'è stato un fall-through, ma ha danneggiato qualcosa che avevi provato a salvare in un caso precedente ". È molto più probabile che sia un bug, secondo me, quindi sarei molto più riluttante a disabilitare la regola "DEAD_STORE" della regola "FALLTHROUGH". –

2

Di solito gli strumenti di analisi bug non piace falltrough in codice, perché nella maggior parte dei casi, l'utente ha appena dimenticato di scrivere la pausa.

Non so se c'è un modo per disattivare specificamente l'avviso con FindBugs ma Checkstyle strumento di riconoscere i commenti speciali come /* * falltrough/ presumere che l'utente vuole davvero il seguente codice essere giustiziato. Mettere questo tipo di commento migliora anche la leggibilità. http://checkstyle.sourceforge.net/config_coding.html#FallThrough

La convenzione del codice Java menziona anche l'uso del commento di fallthrough. http://www.oracle.com/technetwork/java/javase/documentation/codeconventions-142311.html

0

Se i casi non hanno interruzione, una volta che un caso è attivato, l'interruttore passerà attraverso tutti i casi fino a quando non troverà una pausa o una fine dei casi. Se si dispone di un caso predefinito, verrà attivato se il valore dello switch in questo caso foo non corrisponde a nessun altro caso.