Posted at

Javaで三項演算子はどこまで許されるか

More than 1 year has passed since last update.


はじめに

この記事ではJavaに限った話をします。

先日、以下の記事を書きました(タイトル変更してます)。

この記事で、以下のように三項演算子を良い例として挙げました。

String userType = isAdmin ? "管理者" : "一般";

しかし、三項演算子は読みにくいという反応が結構ありました。あくまでシンプルな例として挙げたつもりだったのですが、説明不足だったので、別途記事を書きます。

三項演算子を使っていいのは、単純なもののみに限られるのが自分の中での結論です。


三項演算子とは

三項演算子(ternary operator)は以下のような形をしています。

<条件式> ? <trueのときの値> : <falseのときの値>

どの書き方ならよいかの話をする前に、自分が「どこまでならよい」と感じているのか、その例を書きます。

/*

* 白(ほぼ問題なし)
*/

String userType = isAdmin ? "管理者" : "一般";

String userType = user.isAdmin() ? "管理者" : "一般";

UserType userType = user.isAdmin() ? UserType.ADMIN : UserType.NORMAL;

String userName = user.isAdmin() ? "管理者" : user.getName();

/*
* 白に近いグレー
*/

return user.getType() == UserType.GUEST ? "ゲストユーザ" : user.getName();

/*
* 黒に近いグレー
*/

String userName = user.getType() == UserType.GUEST ? "ゲストユーザ" : user.getName();

/*
* 黒(アウト)
*/

String userName = user.getType() == UserType.GUEST ? "ゲスト" : user.getType() == UserType.ADMIN ? "管理者" : user.getName() + "さん";


何が基準か

三項演算子の定義に戻ります。

<条件式> ? <trueのときの値> : <falseのときの値>

先程の例で、どのようなパターンが良いのか、悪いのかは、以下のように分類できます。


  • 白(ほぼ問題なし)


    • 条件式


      • boolean変数

      • booleanを返すメソッド



    • true/falseのときの値


      • 定数

      • enum

      • getterなど単純な呼び出し





  • グレー


    • 条件式に ==!= での比較が入る



  • 黒(アウト)


    • ネストしている

    • true/falseのときの値が、単純な呼び出し以外



三項演算子が嫌われがちなのは、どこまでが条件式なのか、どこまでがtrueのときの値なのか、頭の中で字句解析、文法解析するコストが高いからです。また、 ==!= での比較が入るとよくないのは、代入の = と見間違えて、一瞬混乱するからです。

なので、単純な書き方以外は避けるようにしています。


どのように書くべきか

以下のように書くこともできますが、後ろ向きな解決案なので、自分は好きではありません。

String userName; // ここでの初期化は無駄なのでしない

if (user.getType() == UserType.GUEST) {
userName = "ゲスト";
} else if (user.userType() == UserType.ADMIN) {
userName = "管理者";
} else {
userName = user.getName() + "さん";
}

自分なら以下のように、メソッドを作ります。この場合はUserクラスのメソッドとして実装できますが。

なお、今回は元の条件式と合わせるためにif文にしましたが、enumの場合はswitch文を使うことが多いです。

private String getName(User user) {

if (user.getType() = UserType.GUEST) {
return "ゲスト";
} else if (user.getType() == UserType.ADMIN) {
return "管理者";
} else {
return user.getName() + "さん";
}
}

// 呼び出し元
String userName = getName(user);


おわりに

自分が思っていたより、読みにくくなるパターンのほうが多かったです。三項演算子を禁止するのはやりすぎだと思いますが、単純なもの以外は使わないくらいでいいと思います。