2011-01-11 2 views
5

Я использую Java 6.Java переключатель случай - по умолчанию против явного перечисления

Предположим, у меня есть перечисление с 6 значений, упорядоченный А до F. О 4 значений были обработаны тем же самым. Я мог бы написать это так.

switch (whichType) { 
    case A: 
    case B: 
    case C: 
    case D: 
     return task(); 
    case E: 
     return someothertask(); 
    case F: 
     return anothersomeothertask(); 
} 

Или вот так.

switch (whichType) { 
    case E: 
     return someothertask(); 
    case F: 
     return anothersomeothertask(); 
    default: 
     return task(); 
} 

Нулевые значения никогда не достигнут этого переключателя.

Что касается краткости и ясности, то второй подход лучше. Что касается явного, я думаю, что первый подход лучше.

Есть ли какие-либо другие плюсы и минусы каждого подхода?

Кроме того, этот простой вопрос представляет собой дубликат, но я попробовал и не мог найти его нигде. Прошу прощения, если я не искал его достаточно хорошо.

+4

Добавить абстрактный метод к вашему классу enum? – Ron

+2

Только для записи: вы _can_ помещаете раздел 'default' вверху, посередине или где-либо еще внутри' switch'; это не должно быть внизу. –

+0

@ ChrisJester-Young Но некоторые статические анализаторы кода запрещают помещать значения по умолчанию в не-нижние позиции. – mjafari

ответ

7

Оба прекрасно, если это перечисление абсолютно, положительно зафиксировано на шесть значений навсегда. В противном случае подумайте о том, какое может быть седьмое значение для перечисления. Если E и F являются единственными двумя возможными выбросами в отношении этой логики switch, и любое другое значение будет падать в том же ковше, что и от A до D, и используйте default. В противном случае вам будет безопаснее иметь case за каждое значение.

3

Предположим, что кто-то добавляет значение в перечисление?

В коде, который я получил, есть такой род конструкция:

switch(mediaType) { 
    case typeA: 
    case typeB: 
    case typeC: 
     DoGeneric(); 
     break; 
    case TypeD: 
     DoSpecial(); 
     break; 
} 

И причина, что это так, что если кто-то добавляет еще одну возможность для перечисления, он не будет компилироваться, пока вы» мы посмотрели места, в которых используется перечисление, и решили, что нужно сделать в этот момент. Нет шансов пропустить один и иметь сложную ошибку.

+0

+1 для случая добавления нового элемента в перечисление. – unholysampler

+4

Ummm ... этот код ** будет компилироваться после того, как кто-то добавит 'typeE'. –

+0

@Stephen C: В зависимости от языка, да, это может (я не развиваюсь на Java). Но, таким образом, ваши инструменты стиля кода могут поднять на него, а с «default» невозможно сказать, было ли это забыто или нет. –

2

Что касается читаемости, я бы сказал, что второй может быть не более ясным. Например, ваш общий случай происходит ПОСЛЕ ваших особых случаев.

Однако реальная проблема, которую я вижу здесь, состоит в том, что две части кода на самом деле не эквивалентны. В первом случае у вас есть шесть явных случаев. Во втором случае у вас есть два явных случая и один случай по умолчанию. Это означает, что если ваш код имеет какую-то ошибку, когда вы получаете случай, который вы не ожидали, случай по умолчанию будет выполняться во втором (и task() все равно будет работать). В результате это принципиально отличается от вашего первого кода.

Помимо этого (определение правильности инструкции оператора), я бы сказал, придерживайтесь того, который лучше всего читает вам. Мне лично нравится первый (потому что он явственен и оставляет место для случая по умолчанию, если это необходимо), но вам придется выбирать на основе ваших предпочтений или стандартов развития вашей компании/команды.

0

Если вы пишете какой-то бизнес-сценарий, и вы ожидаете, что код будет жить и поддерживаться (каким-то другим лицом) на долгие годы, перейдите с опцией 1. Нет ничего плохого в варианте 2, это короткий и ясно, но когда речь идет об ремонтопригодности, я думаю, что вариант 1 побеждает - особенно если случаи связаны с какой-то бизнес-логикой. Техническому инженеру будет намного легче его прочитать.

2

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

switch (whichType) { 
    case A: 
    case B: 
    case C: 
    case D: 
     return task(); 
    case E: 
     return someothertask(); 
    case F: 
     return anothersomeothertask(); 
    default: 
     throw new IllegalArgumentException("Encountered unknown type: " + whichType.name()); 
} 
Смежные вопросы