Подтвердить что ты не робот

Можете ли вы сохранить переменную внутри if-clause?

Я как бы жду ответа "нет" на этот вопрос.

Мне было интересно, если вы можете сохранить переменную одновременно, когда вы проверяете ее в if-clause.

Скажем, у меня есть этот код.

if(foo!=null){
  if(foo.getBar()!=null){
    Bar bar = foo.getBar();
    System.out.println("Success: " + bar);
  } else {
    System.out.println("Failure.");
  }
} else {
  System.out.println("Failure.");
}

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

if(foo!=null && foo.getBar()!=null){
  Bar bar = foo.getBar();
  System.out.println("Success: " + bar);
} else {
  System.out.println("Failure.");
} 

Уже сделан более простой код. если foo имеет значение null, он остановится там и не будет пытаться foo.getBar(в if), поэтому я не получу NPE. Последнее, что я хотел бы улучшить, и главный вопрос: действительно ли мне нужно дважды вызвать foo.getBar()? Было бы неплохо уйти от второго идентичного вызова, если getBar() будет очень тяжелой операцией. Поэтому мне интересно, можно ли как-то сделать что-то похожее на это:

if(foo!=null && (Bar bar = foo.getBar())!=null){
  Bar bar = foo.getBar();
  System.out.println("Success: " + bar);
} else {
  System.out.println("Failure.");
}

Мне нужно было бы разбить его на два разных, если снова, если я хотел бы сделать

Bar bar = foo.getBar();
if (bar!=null) ...
4b9b3361

Ответ 1

Это самое близкое, что вы можете получить:

Bar bar;
if(foo!=null && (bar = foo.getBar())!=null){
  System.out.println("Success: " + bar);
} else {
  System.out.println("Failiure.");
}

Ответ 2

Я использовал эту технику при итерации по строкам из BufferedReader:

BufferedReader br = // create reader
String line
while ((line = br.readLine()) != null) {
    // process the line
}

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

Ответ 3

если вы хотите ограничить область Bar bar, я бы добавил {и} вокруг кода, который опубликовал Майкл.

void foo()
{
    // some code ...

    // this block limits the scope of "Bar bar" so that the rest of the method cannot see 
    // it.
    {
        Bar bar;
        if(foo!=null && (bar = foo.getBar())!=null){
            System.out.println("Success: " + bar);
        } else {
            System.out.println("Failiure.");
        }
    }
}

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

Ответ 4

Из отдела "Мой язык программирования лучше, чем ваш язык программирования": В Groovy вы можете использовать "?." Оператор:

Bar bar = foo?.bar
if (bar != null) {
}

В Java это хороший шаблон (*):

Bar bar = foo == null ? null : foo.getBar();
if (bar != null) {
}

*: Что-то, что вы можете сохранить в кончиках ваших пальцев.

Ответ 5

Три момента, которые полностью не могут ответить на вопрос:

null - зло. Не пишите методы, возвращающие его. Ваша проблема с примером исчезнет.

Я думаю, что вы можете упустить инкапсуляцию. Вместо foo.getBar() можно ли сделать интерфейс foo таким, чтобы вы выполняли операцию "Сообщить не спрашивать"?

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