Ответ 1
Это самое близкое, что вы можете получить:
Bar bar;
if(foo!=null && (bar = foo.getBar())!=null){
System.out.println("Success: " + bar);
} else {
System.out.println("Failiure.");
}
Я как бы жду ответа "нет" на этот вопрос.
Мне было интересно, если вы можете сохранить переменную одновременно, когда вы проверяете ее в 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) ...
Это самое близкое, что вы можете получить:
Bar bar;
if(foo!=null && (bar = foo.getBar())!=null){
System.out.println("Success: " + bar);
} else {
System.out.println("Failiure.");
}
Я использовал эту технику при итерации по строкам из BufferedReader:
BufferedReader br = // create reader
String line
while ((line = br.readLine()) != null) {
// process the line
}
Итак, да, вы можете выполнить назначение, а результат - с левой стороны, который вы можете проверить. Тем не менее, неявно объявлять переменные внутри теста, так как тогда они будут привязаны только к этому выражению.
если вы хотите ограничить область 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 или нет.
Из отдела "Мой язык программирования лучше, чем ваш язык программирования": В Groovy вы можете использовать "?." Оператор:
Bar bar = foo?.bar
if (bar != null) {
}
В Java это хороший шаблон (*):
Bar bar = foo == null ? null : foo.getBar();
if (bar != null) {
}
*: Что-то, что вы можете сохранить в кончиках ваших пальцев.
Три момента, которые полностью не могут ответить на вопрос:
null
- зло. Не пишите методы, возвращающие его. Ваша проблема с примером исчезнет.
Я думаю, что вы можете упустить инкапсуляцию. Вместо foo.getBar()
можно ли сделать интерфейс foo
таким, чтобы вы выполняли операцию "Сообщить не спрашивать"?
Побочные эффекты в выражении имеют тенденцию вызывать плохой код. Предпочитайте больше, проще линий, чтобы уменьшить количество багги. Обычное исключение при использовании ++
для увеличения индекса при доступе к буферу или аналогичных алгоритмов стиля итератора.