2011-12-19 3 views
18

У меня есть оператор switch, как показано ниже. Обратите внимание, что нет перерыва. Findbugs сообщает об ошибке только во втором случае. Ошибка: оператор switch найден там, где один случай попадает в следующий случай.Переключатель без перерыва

switch(x) { 

    case 0: 
     // code 

    case 1: 
     // code 

    case 2: 
     // code 
} 
+3

что сообщение об ошибке сказать? –

+9

И проблема в том, что ...? – fge

+0

Вы уверены, что это не предупреждение, а ошибка? – xagyg

ответ

2

Без перерыва они будут падать, хотя друг в друга, так что если x == 0 вы будете пройти через весь код в каждом блоке сазе. Findbugs может быть ошибочным в отношении ошибки, или это может быть условие ошибки без перерыва, то есть что-то в case 0 заставляет что-то в case 1 сломаться.

Без точного кода и ошибки я больше не могу помочь. Является ли отсутствие перерывов преднамеренным?

60

Findbugs отмечает, что падение от одного case к следующему обычно не является хорошей идеей, если в первом есть какой-либо код (хотя иногда его можно использовать для хорошего эффекта). Поэтому, когда он видит второй case и не break, он сообщает об ошибке.

Так, например:

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

Это вполне допустимо Java, но это, вероятно, не делать то, что задумал автор: Если foo является 0, все три функции doSomething, doSomethingElse, и doSomeOtherThing запустить (в указанном порядке). Если foo - 1, только doSomethingElse и doSomeOtherThing пробег. Если foo - любое другое значение, выполняется только doSomeOtherThing.

В отличие:

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

Здесь только одна из функций будет работать, в зависимости от значения foo.

Поскольку это общая ошибка кодирования, чтобы забыть break, такие инструменты, как Findbugs, помечены для вас.

Там в общее пользование, случай, когда у вас есть несколько case заявления в ряд с не промежуточный код:

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

Там, мы хотим вызвать doSomething если foo является 0или1. Большинство инструментов не будут отмечать это как возможную ошибку кодирования, потому что код case 0 отсутствует до case 1, и это довольно распространенный шаблон.

+1

Действительно ли 'break' нужен в конце? – kcpr

+2

@kcpr: Строго говоря, вам не нужен «break;» в последнем случае коммутатора ('default' в приведенном выше). Но я предпочитаю последовательность. Это чисто вопрос стиля, тот же байт-код создается в любом случае. (Это, конечно, не верно, если вы не оставляете никаких других * 'break;'.) –

+0

Это очень хорошее описание общей проблемы и того, как работает коммутатор, но на самом деле не отвечает на вопрос OP - хотя, строго говоря, ОП на самом деле не задавал вопрос ... – Tasgall

3

Коммутационные провалы подпадают под категорию «Найденные коды». Я думаю, что это только флаг первого появления провала в инструкции switch, чтобы сократить количество сообщений об ошибках.

4

Я написал их в качестве комментариев, но потом это не видно. Я превращаю их в ответ. Это фактически расширение до T.J.Crowder's answer.

Вы можете найти соответствующее правило, по которому Findbugs сообщает об ошибке here.

Вы можете запретить Findbugs сообщать об ошибках такого типа, создав файл xml со следующим содержимым, скажем filter.xml и запустив инструмент с помощью опции -exclude filter.xml. См. filters on Findbugs.

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

On Stack Overflow, на самом деле вполне приемлемо редактировать чужой ответ, чтобы добавить полезную информацию (например, выше). Действуй! –

+1

@ T.J.Crowder, к сожалению, мои правки были отклонены, мне пришлось отменить мой ответ. Спасибо за предложение в любом случае. – melihcelik

+0

Я подозреваю, что фактическое правило было более общим ['SF_SWITCH_FALLTHROUGH'] (http: // findbugs.sourceforge.net/bugDescriptions.html#SF_SWITCH_FALLTHROUGH). 'SF_DEAD_STORE_DUE_TO_SWITCH_FALLTHROUGH' означает:« не только произошел провал, но он сбивал то, что вы пытались сохранить в предыдущем случае ». На мой взгляд, это скорее всего будет ошибкой, поэтому я бы гораздо более не решался отключить правило «DEAD_STORE», чем правило «FALLTHROUGH». –

2

Обычно инструментам анализа ошибки не нравятся проваливаются в коде, так как в большинстве случаев, пользователь просто забыл написать перерыв.

Я не знаю, есть ли способ специально отключить предупреждение с FindBugs но Checkstyle инструмента распознают специальные комментарии, такие как /* проваливаюсь */ предположить, что пользователь действительно хочет следующий код для выполнения. Помещение такого комментария также улучшает читаемость. http://checkstyle.sourceforge.net/config_coding.html#FallThrough

Соглашение об использовании Java также упоминает использование провала комментария. http://www.oracle.com/technetwork/java/javase/documentation/codeconventions-142311.html

0

Если ваши случаи не имеют разрыва, то когда триггерный ключ случая будет проходить через все случаи, пока не найдет разрыв или конец случаев. Если у вас есть случай по умолчанию, он будет срабатывать, если значение вашего переключателя в этом случае foo не соответствует ни одному другому случаю.

Смежные вопросы