Преимущество переключается если еще оператор

Как будто вы пытаетесь получить доступ к объекту, который является null. Рассмотрим ниже пример:

TypeA objA;

. В это время вы только что объявили этот объект, но не инициализировали или не инициализировали. И всякий раз, когда вы пытаетесь получить доступ к каким-либо свойствам или методам в нем, он будет генерировать NullPointerException, что имеет смысл.

См. Также этот пример:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
162
задан sepp2k 8 March 2019 в 20:48
поделиться

19 ответов

Используйте переключатель.

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

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

152
ответ дан Drew Dormann 23 November 2019 в 21:22
поделиться

Наблюдение, поскольку у Вас только есть 30 кодов ошибки, код Ваша собственная таблица переходов, тогда Вы делаете весь выбор оптимизации сами (переход всегда будет самым быстрым), вместо того, чтобы надеяться, что компилятор сделает правильную вещь. Это также делает код очень маленьким (кроме статического объявления таблицы переходов). Это также имеет дополнительную льготу, что с отладчиком можно изменить поведение во времени выполнения, должен Вы так нуждаться, только путем ввода по абсолютному адресу данных таблицы непосредственно.

0
ответ дан Greg Whitfield 23 November 2019 в 21:22
поделиться

Я сказал бы ПЕРЕКЛЮЧАТЕЛЬ использования. Таким образом, только необходимо реализовать отличающиеся результаты. Ваши десять идентичных случаев могут использовать значение по умолчанию. Если одно изменение все, Вы должны, является явно реализацией изменение, никакая потребность отредактировать значение по умолчанию. Также намного легче добавить или удалить случаи из ПЕРЕКЛЮЧАТЕЛЯ, чем отредактировать ЕСЛИ и ELSEIF.

switch(numerror){
    ERROR_20 : { fire_special_event(); } break;
    default : { null; } break;
}

, возможно, даже тестируют Ваше условие (в этом случае numerror) против списка возможностей, массив, возможно, таким образом, Ваш ПЕРЕКЛЮЧАТЕЛЬ даже не используется, если определенно не будет результат.

0
ответ дан lewis 23 November 2019 в 21:22
поделиться

Im не человек, чтобы сказать Вам о скорости и использовании памяти, но рассмотрении переключателя statment является адской партией, легче понять тогда большое если оператор (особенно 2-3 месяца по линии)

0
ответ дан Ed Brown 23 November 2019 в 21:22
поделиться

Я выбрал бы, если оператор ради ясности и соглашения, хотя я уверен, что некоторые не согласились бы. В конце концов, Вы желаете сделать что-то if, некоторое условие верно! Наличие переключателя с одним действием кажется немногим... unneccesary.

0
ответ дан William Keller 23 November 2019 в 21:22
поделиться

Эстетически я склонен одобрять этот подход.

unsigned int special_events[] = {
    ERROR_01,
    ERROR_07,
    ERROR_0A,
    ERROR_10,
    ERROR_15,
    ERROR_16,
    ERROR_20
 };
 int special_events_length = sizeof (special_events) / sizeof (unsigned int);

 void process_event(unsigned int numError) {
     for (int i = 0; i < special_events_length; i++) {
         if (numError == special_events[i]) {
             fire_special_event();
             break;
          }
     }
  }

Делают данные немного более умными, таким образом, мы можем сделать логику немного более немой.

я понимаю, что это выглядит странным. Вот вдохновение (от того, как я сделал бы это в Python):

special_events = [
    ERROR_01,
    ERROR_07,
    ERROR_0A,
    ERROR_10,
    ERROR_15,
    ERROR_16,
    ERROR_20,
    ]
def process_event(numError):
    if numError in special_events:
         fire_special_event()
1
ответ дан mbac32768 23 November 2019 в 21:22
поделиться

Я не уверен в наиболее успешной практике, но я использовал бы переключатель - и затем захватил бы намеренный, проваливаются через 'значение по умолчанию'

1
ответ дан da5id 23 November 2019 в 21:22
поделиться

переключатель определенно предпочтен. Легче посмотреть на список переключателя случаев & знайте наверняка, что это делает, чем считать длинное если условие.

дублирование в if условие плохо обращается с глазами. Предположим, что один из эти == был записан !=; Вы заметили бы? Или если один экземпляр 'numError' был записан 'nmuError', который просто, оказалось, скомпилировал?

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

Что касается производительности, Ваш лучший выбор состоит в том, чтобы использовать профилировщика для измерения уровня приложения в условиях, которые подобны тому, что Вы ожидаете в дикой природе. Иначе Вы, вероятно, оптимизируете в неправильном месте и неправильным способом.

1
ответ дан Jay Bazuzi 23 November 2019 в 21:22
поделиться

Я соглашаюсь с compacity решения для переключателя, но IMO Вы угон переключателя здесь.
цель переключателя состоит в том, чтобы иметь отличающийся обработка в зависимости от значения.
, Если бы необходимо было объяснить алгоритм в псевдокоде, Вы использовали бы если потому что, семантически, вот что это значит: , если whatever_error делают это ...
Поэтому, если Вы не намереваетесь когда-нибудь изменить свой код для имения определенного кода для каждой ошибки, я использовал бы если .

1
ответ дан François 23 November 2019 в 21:22
поделиться

Если Ваши случаи, вероятно, останутся сгруппированными в будущем - если больше чем один случай будет соответствовать одному результату - переключатель может оказаться легче считать и поддержать.

1
ответ дан TSomKes 23 November 2019 в 21:22
поделиться

IMO это - идеальный пример того, какой переключатель проваливается, был сделан для.

2
ответ дан Nescio 23 November 2019 в 21:22
поделиться

Используйте переключатель, это - то, для чего это и что ожидают программисты.

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

5
ответ дан Martin Beckett 23 November 2019 в 21:22
поделиться

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

5
ответ дан Bdoserror 23 November 2019 в 21:22
поделиться

Переключатель, если только для удобочитаемости. Гигант, если операторы более трудно поддержать и тяжелее читать, по-моему.

ERROR_01://намеренный проваливаются

, или

(ERROR_01 == numError) ||

позже более подвержено ошибкам и требует большего количества ввода и форматирования, чем первое.

6
ответ дан scubabbl 23 November 2019 в 21:22
поделиться

Компилятор оптимизирует, он так или иначе - идет для переключателя, поскольку это является самым читаемым.

18
ответ дан Alexandra Franks 23 November 2019 в 21:22
поделиться

Переключатель быстрее.

Просто if/else-ing 30 попытки различные значения в цикле, и сравнивают его с тем же кодом с помощью переключателя для наблюдения, насколько быстрее переключатель.

Теперь, эти переключатель имеет одну настоящую проблему : переключатель должен знать во время компиляции значения в каждом случае. Это означает что следующий код:

// WON'T COMPILE
extern const int MY_VALUE ;

void doSomething(const int p_iValue)
{
    switch(p_iValue)
    {
       case MY_VALUE : /* do something */ ; break ;
       default : /* do something else */ ; break ;
    }
}

не скомпилирует.

Большинство людей будет тогда использовать, определяет (Aargh!), и другие объявит и определит постоянные переменные в той же единице компиляции. Например:

// WILL COMPILE
const int MY_VALUE = 25 ;

void doSomething(const int p_iValue)
{
    switch(p_iValue)
    {
       case MY_VALUE : /* do something */ ; break ;
       default : /* do something else */ ; break ;
    }
}

Так, в конце, разработчик должен выбрать между "скоростью + ясность" по сравнению со "связью кода".

(Не то, чтобы переключатель не может быть записан для сбивания с толку как ад... Большинство переключатель, который я в настоящее время вижу, имеет эту "запутывающую" категорию"... Но это - другая история...)

Редактирование 21.09.2008:

bk1e добавил следующий комментарий: " константы Определения как перечисления в заголовочном файле другой способ обработать это".

, Конечно, это.

точка типа экстерна должна была разъединить значение из источника. Определение этого значения как макрос, как простое объявление интервала константы, или как раз когда перечисление имеет побочный эффект встраивания значения. Таким образом, если определение, перечисление значений или изменение значения интервала константы, перекомпиляция была бы необходима. Объявление экстерна означает нет никакой потребности перекомпилировать в случае изменения значения, но в другой руке, не лишает возможности использовать переключатель. Заключение, являющееся Используя переключатель, увеличит связь между кодом переключателя и переменными, используемыми в качестве случаев . Когда это будет в порядке, затем используйте переключатель. Когда это не, тогда, не удивительно.

.

Редактирование 15.01.2013:

Vlad Lazarenko прокомментировал мой ответ, дав ссылку на его всестороннее исследование ассемблерного кода, сгенерированного переключателем. Очень enlightning: http://741mhz.com/switch/

20
ответ дан Calvin1602 23 November 2019 в 21:22
поделиться

Для особого случая, который Вы обеспечили в своем примере, самый ясный код, вероятно:

if (RequiresSpecialEvent(numError))
    fire_special_event();

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

bool RequiresSpecialEvent(int numError)
{
    return specialSet.find(numError) != specialSet.end();
}

я не предполагаю, что это - лучшая реализация RequiresSpecialEvent, просто что это - опция. Можно все еще использовать переключатель или если еще цепочка, или таблица поиска или некоторая побитовая обработка на значении, безотносительно. Чем более неясным Ваш процесс принятия решений становится, тем больше значения Вы получите на наличие его в изолированной функции.

42
ответ дан Mark Ransom 23 November 2019 в 21:22
поделиться

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

я предпочитаю, если операторы по операторам выбора, потому что они более читаемы, и более гибки - можно добавить другие условия не на основе числового равенства, как "|| макс. < минута". Но для простого случая Вы отправили здесь, он действительно не имеет значения, просто делает то, что является самым читаемым Вам.

1
ответ дан SquareCog 23 November 2019 в 21:22
поделиться

Я знаю его old, но

public class SwitchTest {
static final int max = 100000;

public static void main(String[] args) {

int counter1 = 0;
long start1 = 0l;
long total1 = 0l;

int counter2 = 0;
long start2 = 0l;
long total2 = 0l;
boolean loop = true;

start1 = System.currentTimeMillis();
while (true) {
  if (counter1 == max) {
    break;
  } else {
    counter1++;
  }
}
total1 = System.currentTimeMillis() - start1;

start2 = System.currentTimeMillis();
while (loop) {
  switch (counter2) {
    case max:
      loop = false;
      break;
    default:
      counter2++;
  }
}
total2 = System.currentTimeMillis() - start2;

System.out.println("While if/else: " + total1 + "ms");
System.out.println("Switch: " + total2 + "ms");
System.out.println("Max Loops: " + max);

System.exit(0);
}
}

Изменение количества циклов сильно меняет:

В то время как if / else: 5 мс Переключатель: 1 мс Максимальное количество циклов: 100000

В то время как if / else: 5 мс Переключатель: 3 мс Максимальное количество циклов: 1000000

В то время как if / else: 5 мс Переключатель: 14 мс Максимальное количество циклов: 10000000

В то время как if / else: 5 мс Переключатель: 149 мс Максимальное количество циклов: 100000000

(добавьте больше операторов, если хотите)

0
ответ дан 23 November 2019 в 21:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: