Java пока-циклы - PullRequest
       59

Java пока-циклы

2 голосов
/ 25 февраля 2010

Итак, переписывая код, я наткнулся на что-то вроде:

Метод 1

while ( iter.hasNext() ) {
    Object obj = iter.next();
    if ( obj instanceof Something ) {
        returnValue = (Something) obj;
        break;
    }
}

Я переписал это как следующее, не задумываясь (реальная цель переписывания была для другой логики в этом методе):

Метод 2

while ( (iter.hasNext()) && (returnValue == null) ) {
    Object obj = iter.next();
    if ( obj instanceof Something ) {
        returnValue = (Something) obj;
    }
}

Лично у меня нет сильных предпочтений, и я не вижу в этом ничего плохого. Может ли кто-нибудь еще думать о преимуществах или последствиях использования любого из этих подходов? Переменная returnValue возвращается. Что бы чувствовали люди, если бы это был последний блок в методе, и он только что вернулся?

РЕДАКТИРОВАТЬ: Итак, вот что я делаю: в настоящее время этот метод берет набор авторизаций и проверяет их - возвращает логическое значение. Этот метод позволяет группировать, так что вы можете указать, по крайней мере, один или все (то есть, если хотя бы одна авторизация действительна, передайте весь набор). Однако этот метод не поддерживает уровни авторизации, что я и изменяю, чтобы каждый уровень мог указывать различные группы. Все эти биты являются просто справочной информацией ... не имеет ничего общего с приведенным выше кодом - альтернативный метод используется для выполнения вышеуказанного блока кода.

Ответы [ 9 ]

9 голосов
/ 25 февраля 2010

Для меня яснее было бы извлечь это как собственный метод; тогда вы можете просто вернуть значение, а не присваивать его локальному.

while (iter.hasNext()) {
    Object obj = iter.next();
    if (obj instanceof Something)
        return (Something)obj;
}
return null;

Еще лучше было бы цикл foreach

for (Object o : yourList)
    if (o instanceof Something)
        return (Something)o
return null;
7 голосов
/ 25 февраля 2010

Мне нравится первое, так как более понятно, почему вы выходите из цикла. Он говорит: «Если это условие истинно, установите значение и разорвите цикл, все готово». Другой занял у меня еще секунду или около того, но, как вы сказали, большой разницы нет.

3 голосов
/ 25 февраля 2010

Я предпочитаю явный переход (будь то break или return).Мне сложно сформулировать почему, но я могу сравнить это с написанием активным и пассивным голосом.Конечно, это просто стиль, но активный читать намного проще.

2 голосов
/ 25 февраля 2010

Они эквивалентны в этом случае, но это уже не тот случай, если вы хотите что-то сделать после условия if, что часто имеет место.

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

2 голосов
/ 25 февраля 2010

Одна мысль состоит в том, что метод должен иметь только одно возвращаемое утверждение / точку в конце метода.

Я склонен использовать то, что яснее в конкретных обстоятельствах.

В сторону:

1) Если вы переписываете код, который работает (при условии, что он работает)?

2) Если вы переписываете код, который не имеет тестов (при условии, что его нет)?

1 голос
/ 26 февраля 2010

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

Object returnValue=null; //Notice in your original code
while(iter.hasNext()){
    Object kind=iter.next()
    switch(kind.getType()){
       case "fish": 
       case "reptile":
          if(returnValue!=bird|returnValue!=mammal)
               returnValue=(coldblood) kind;
          break;
       case "bird":
       case "mammal":
          returnValue=(coldblood) kind;
          break;
       case default:
          //Fall-through
    }
}
return returnValue;

Так вот что я должен сказать:

  1. Вы сказали, что вам нужно реализовать несколько уровней разрешений, я считаю, что вам придется перебирать всю коллекцию.
  2. Сказав это, я рекомендую использовать метод 1 - то есть, если вам нужно сломаться. Ключевое слово break более понятно и немного быстрее. (На один прыжок меньше, но незначительный)
1 голос
/ 25 февраля 2010

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

Я решил спросить, что делает цикл - две вещи, он проверяет наличие объекта типа Fish и делает этот объект доступным вне цикла. Если мы разделим две обязанности, мы получим:

Object obj = null;
while (iter.hasNext() && !(obj instanceof Fish)) {
  obj = iter.next();
}
if (obj instanceof Fish) {
  returnValue = (Fish) obj;
}

Мне все еще не нравится ... возможно, это экземпляр или использование Object или даже просто природа Iterator, но это не похоже на хороший код.

1 голос
/ 25 февраля 2010

Очевидно, что первая форма намного лучше, потому что она менее сложна. Если вы ничего не делаете с returnValue, вы можете просто вернуть его, как только найдете совпадение.

1 голос
/ 25 февраля 2010

Метод 1 гораздо яснее в том, что он делает, он прерывает цикл, когда obj instanceof Something==true, хотя метод 2 также довольно очевиден. Другим небольшим преимуществом метода 1 является то, что он немного быстрее, так как метод 2 выполняет еще одну проверку каждого цикла и еще одну проверку, чем метод 1. Что если проверка заняло более 1 минуты?

Очевидно, что метод 1 лучше и легче понять.

...