Javaには次のような文が散らばっています。
if(cage.getChicken() != null) {
dinner = cage.getChicken();
} else {
dinner = getFreeRangeChicken();
}
getChicken()
を2回呼び出してから、返されたオブジェクトをdinner
に割り当てることができます。
これは、次のように1行で記述することもできます。
dinner = cage.getChicken() != null? cage.getChicken() : getFreeRangeChicken();
しかし残念ながら、getChicken()
への呼び出しはまだ2つあります。
もちろん、ローカル変数を割り当てた後、nullでない場合は三項演算子を再度使用して割り当てることができますが、これは2行であり、あまりきれいではありません。
FutureMeal chicken = cage.getChicken();
dinner = chicken != null? chicken : getFreeRangeChicken();
だから言う方法はありますか?
変数var =ある値がnullでない場合、ある値OR他の値。
そして、私はここで構文を話しているだけだと思います。コードがコンパイルされた後、おそらくパフォーマンスの意味でコードがどのように書かれたかはそれほど違いはありません。
これは非常に一般的なコードであるため、それを書くためのワンライナーがあれば素晴らしいでしょう。
他の言語にはこの機能がありますか?
Javaには合体演算子がないため、1回の呼び出しでの割り当てには、明示的な一時を使用したコードが最適です。
次のように、結果変数を一時的なものとして使用できます。
dinner = ((dinner = cage.getChicken()) != null) ? dinner : getFreeRangeChicken();
ただし、これは読みにくいです。
Lokiの答えと同じ原理ですが、短いです。短くしても自動的に良くなるわけではないことに注意してください。
dinner = Optional.ofNullable(cage.getChicken())
.orElse(getFreerangeChicken());
注:Optional
のこの使用は、JDKの設計者およびオプション機能の設計者によって明示的に推奨されていません。新しいオブジェクトを割り当てて、毎回すぐに破棄します。しかし一方で、それは非常に読みやすくなる可能性があります。
Java 1.8をまだ使用しておらず、commons-langを使用する気がない場合は、 org.Apache.commons.lang3.ObjectUtils#defaultIfNull を使用できます。
あなたのコードは次のようになります:
dinner = ObjectUtils.defaultIfNull(cage.getChicken(),getFreeRangeChicken())
Java 1.8を使用すると、Optional
を使用できます
public class Main {
public static void main(String[] args) {
//example call, the methods are just dumb templates, note they are static
FutureMeal meal = getChicken().orElse(getFreeRangeChicken());
//another possible way to call this having static methods is
FutureMeal meal = getChicken().orElseGet(Main::getFreeRangeChicken); //method reference
//or if you would use a Instance of Main and call getChicken and getFreeRangeChicken
// as nonstatic methods (assume static would be replaced with public for this)
Main m = new Main();
FutureMeal meal = m.getChicken().orElseGet(m::getFreeRangeChicken); //method reference
//or
FutureMeal meal = m.getChicken().orElse(m.getFreeRangeChicken()); //method call
}
static Optional<FutureMeal> getChicken(){
//instead of returning null, you would return Optional.empty()
//here I just return it to demonstrate
return Optional.empty();
//if you would return a valid object the following comment would be the code
//FutureMeal ret = new FutureMeal(); //your return object
//return Optional.of(ret);
}
static FutureMeal getFreeRangeChicken(){
return new FutureMeal();
}
}
getChicken
のロジックを実装して、nullの代わりにOptional.empty()
を返すか、Optional.of(myReturnObject)
を返します。ここで、myReturnObject
はchicken
です。
その後、getChicken()
を呼び出すことができ、Optional.empty()
を返す場合、orElse(fallback)
はフォールバックが何であれ、2番目のメソッドになります。
public static <T> T defaultWhenNull(@Nullable T object, @NonNull T def) {
return (object == null) ? def : object;
}
例:
defaultWhenNull(getNullableString(), "");
常にdefault value
を評価します(cond ? nonNull() : notEvaluated()
に対して)
これは、デフォルト値の代わりにCallableを渡すことで回避できますが、多少複雑で動的性が低くなります(たとえば、パフォーマンスに問題がある場合)。
ちなみに、Optional.orElse()
を使用すると同じ欠点があります;-)
Java 9以降、 Objects#requireNonNullElse があります。
public static <T> T requireNonNullElse(T obj, T defaultObj) {
return (obj != null) ? obj : requireNonNull(defaultObj, "defaultObj");
}
あなたのコードは
dinner = Objects.requireNonNullElse(cage.getChicken(), getFreeRangeChicken());
これは1行で、getChicken()
を1回だけ呼び出すため、両方の要件が満たされます。
2番目の引数もnull
にできないことに注意してください。このメソッドは、戻り値の非ヌルを強制します。
代替案も考慮してください Objects#requireNonNullElseGet :
public static <T> T requireNonNullElseGet(T obj, Supplier<? extends T> supplier)
最初の引数がnull
でない場合は2番目の引数も評価しませんが、Supplier
を作成するオーバーヘッドがあります。
dinner = cage.getChicken();
if(dinner == null) dinner = getFreeRangeChicken();
または
if( (dinner = cage.getChicken() ) == null) dinner = getFreeRangeChicken();
あるいは、Java8では、NullableまたはNotNull注釈を必要に応じて使用できます。
public class TestingNullable {
@Nullable
public Color nullableMethod(){
//some code here
return color;
}
public void usingNullableMethod(){
// some code
Color color = nullableMethod();
// Introducing assurance of not-null resolves the problem
if (color != null) {
color.toString();
}
}
}
public class TestingNullable {
public void foo(@NotNull Object param){
//some code here
}
...
public void callingNotNullMethod() {
//some code here
// the parameter value according to the explicit contract
// cannot be null
foo(null);
}
}