Есть ли какое-либо заметное различие между если и если еще?

Учитывая следующие фрагменты кода, там какое-либо заметное различие?

public boolean foo(int input) {
   if(input > 10) {
       doStuff();
       return true;
   }
   if(input == 0) {
       doOtherStuff();
       return true;
   }

   return false;
}

по сравнению с.

public boolean foo(int input) {
   if(input > 10) {
      doStuff();
      return true;
   } else if(input == 0) {
      doOtherStuff();
      return true;
   } else {
      return false;
   }
}

Или был бы единственный принцип выхода быть лучше здесь с этой частью кода...

public boolean foo(int input) {
   boolean toBeReturned = false;
   if(input > 10) {
      doStuff();
      toBeReturned = true;
   } else if(input == 0) {
      doOtherStuff();
      toBeReturned = true;
   }

   return toBeReturned;
}

Есть ли какое-либо заметное различие в производительности? Вы чувствуете, что каждый более или менее удобен в сопровождении/читаем, чем другие?

8
задан Drew 20 April 2010 в 19:00
поделиться

9 ответов

Во втором примере вы очень четко заявляете, что оба условия являются взаимоисключающими.
С первым все не так ясно, и в том (маловероятном) случае, когда назначение на вход добавляется между обоими if, логика изменится.
Предположим, кто-то в будущем добавит input = 0 перед вторым if.
Конечно, это маловероятно, но если мы говорим здесь о ремонтопригодности, if-else ясно говорит, что существуют взаимоисключающие условия, а множество ifs нет, а они не настолько зависимы друг от друга, как блоки if-else.

править: Теперь, когда я вижу, в этом конкретном примере предложение return усиливает взаимную исключительность, но опять же, мы говорим о ремонтопригодности и удобочитаемости.

В любом случае, насчет производительности, если это написано на Java, вам не нужно заботиться о производительности пары блоков if, если бы он был встроен в C в очень медленное оборудование, возможно, но, конечно, не с java.

10
ответ дан 5 December 2019 в 09:24
поделиться

Подумайте об этом случае, когда два примера не будут похожи:

    public boolean foo(int input) {
        if (input > 10) {
            // doStuff();
            return true;
        }
        System.out.println("do some other intermediary stuff");
        if (input == 0) {
            // doOtherStuff();
            return true;
        }

        return false;
    }

vs.

    public boolean foo(int input) {
        if (input > 10) {
            // doStuff();
            return true;
        } 
        //System.out.println("doing some intermediary stuff... doesn't work");
        else if (input == 0) {
            // doOtherStuff();
            return true;
        } else {
            return false;
        }
        return false;
    }

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

Что касается производительности, я думаю, что различия слишком малы, чтобы их принимать во внимание, для любого обычного java-приложения, написанного здравомыслящими программистами :).

0
ответ дан 5 December 2019 в 09:24
поделиться

В вашем последнем примере не делайте этого:

public boolean foo(int input) {
   boolean toBeReturned = false;
   if(input > 10) {
      doStuff();
      toBeReturned = true;
   } else if(input == 0) {
      doOtherStuff();
      toBeReturned = true;
   }

   return toBeReturned;
}

, а вот это (обратите внимание на использование Java final ):

public boolean foo(int input) {
   final boolean toBeReturned;    // no init here
   if(input > 10) {
      doStuff();
      toBeReturned = true;
   } else if(input == 0) {
      doOtherStuff();
      toBeReturned = true;
   } else {
      toBeReturned = false;
   }
   return toBeReturned;
}

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

Таким образом вы уверены , что не забудете инициализировать свое возвращаемое значение. Это замечательно, если позже вы решите, что вам все-таки нужно другое условие.

Я делаю это все время и тем более с тех пор, как начал использовать IntelliJ IDEA (версия 4 или около того, давным-давно), и это спасло меня от множества глупых ошибок отвлечения внимания ...

Некоторые люди будут утверждать, что это слишком много кода для такого простого случая, но он полностью упускает из виду суть: суть в том, чтобы прояснить намерение, чтобы код легко читался и мог быть легко расширен позже, не забывая случайно назначить toBeReturned ] и, случайно не забыв вернуться из более позднего предложения, вы можете добавить.

В противном случае, если бы «краткость» было названием игры, я бы написал:

public boolean foo(int a) {
  return a > 10 ? doStuff() : a == 0 ? doOtherStuff() : false; 
}

Где и doStuff , и doOtherStuff вернут истину.

1
ответ дан 5 December 2019 в 09:24
поделиться

Версии №1 и №2 могут быть быстрее, чем №3, но я полагаю, что разница в производительности минимальна. Я бы предпочел сосредоточиться на удобочитаемости .

Лично я бы никогда не использовал версию №2. Между №1 и №3 я бы выбрал тот, который дает наиболее читаемый код для рассматриваемого случая. Мне не нравится много точек выхода в моих методах, потому что это затрудняет анализ кода.Однако есть случаи, когда поток становится более ясным, когда мы немедленно выходим из некоторых особых случаев и продолжаем работу с основными случаями.

0
ответ дан 5 December 2019 в 09:24
поделиться

Семантически - нет.С точки зрения производительности это зависит от компилятора, то есть от того, может ли он определить, что оба условия не могут выполняться одновременно. Готов поспорить, что стандартный компилятор Sun может. Использовать ли принцип единого выхода - зависит от вкусов. Я лично ненавижу это.

0
ответ дан 5 December 2019 в 09:24
поделиться

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

-1
ответ дан 5 December 2019 в 09:24
поделиться

В вашем случае второе if будет вызываться только в том случае, если первое if не удалось, поэтому здесь это менее важно, но если ваше первое if что-то сделало и не вернулось, второе if (которое тогда всегда будет ложным) все равно будет проверено, если оно не было в else-if.

Другими словами, есть случаи, когда разница между if-else-if и if-if имеет значение, но это не один из них.

Пример: попробуйте это, а затем попробуйте после удаления else. Вы получаете два разных результата:

int someNumber = 1;
if(someNumber < 5)
{
    someNumber += 5;
    Console.WriteLine("First call.");
}
else if(someNumber >= 5)
{
    Console.WriteLine("Second call.");
}
0
ответ дан 5 December 2019 в 09:24
поделиться

Используйте любую форму лучше описывает ваше намерение.

Не следуйте принципу единственного выхода, если все так просто - это только усложняет задачу.

4
ответ дан 5 December 2019 в 09:24
поделиться
  • В первом:

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

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

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

  • Мне не нравится третья, она заставляет меня искать переменную return, и легче найти ключевое слово return

О скоростных характеристиках они (почти) идентичны. Не беспокойтесь об этом.

4
ответ дан 5 December 2019 в 09:24
поделиться
Другие вопросы по тегам:

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