三項演算子がわかりにくい話

三項演算子がわかりにくいという話があるそうだが,なんでだろうか.
条件分岐により返却値を選択するような式ではよく使うと思うが,世の中ではコーディング記述で禁止するようなところもあるみたいだ.

なぜわかりにくいんだろうか.
1点目としては,とにかく'?'とか':'が直感的に意味がよくわからないという点がある.つまり,

return (object!=null) ? object.toString() : "null";

とか.
'?',特に':'は,四則演算子でもなければ,英語でもない.ビット演算子のようなアスキーアート(とは言わないか)でもない.にもかかわらず意味をわかれっていうことだわかりにくいのかもしれない.あと,評価式で意味を成すために,最低二つの演算子('?'とか':')が,必要な式ってのは,多分これしかない(多分).
しかし,さすがにこんなことは覚えろボケとしか言いようがない.そもそもperlとかに比べると遙かに簡単だ. どちらかと言えば,いかにJavaがシンプルかを言っていて,オマイラもっと勉強しろって気がする.

次に,これがあくまで評価式であると言うことを知らずに,なんとなく使ってしまって,完全なif-thenの代わりにできると考えたり,2個目と3個目の式で相容れない型を使ってしまう場合があるという問題もある.
たとえば,

// 2個目のオペランドはvoid,3個目はオペランドっていうか,文
(object!=null) ? System.out.println("Not Null!") : return ERROR_01;

/* 2個目のオペランドと3個目のオペランドのどちらかがどちらかに代入可能である必要がある.*1 */
Object object = (oldObject!=null) ? new String("0"): new Integer(1);

とか.こういう時に,コンパイルエラーが出て,わけがわからず敬遠して,「3項演算子はわかりにくい!」となることもあるだろう.

最後に言えば,たくさん並べると,可読性の悪いのが嫌だと言う人もいるだろう.
たとえば,

String result1 = a==1 ? b!=2 ? "Red" : "Blue" : "Green";
String result2 = a==1 ? "Red" : b==2 ? "Blue" : "Green";

これらは両方とも,コンパイルに通るのだが,1回ネストしただけでもよくわからない(あえて,括弧をいれずに可読性を下げているが)気もする.
さらに,すべてのオペランドがbooleanだったら,

boolean res = p ? q: r ? s ? t :u :v ? w: x;

さすがにわけがわからない. そりゃ,ハテナが4つもつくよという話である.
さらに,この演算子の右結合の原則を知らなければ,間違った解釈もしかねない.これは極端だが,ネストはあまりしないほうがよくて,するならカッコぐらいつけなされということか.

まとめると,

  1. ?とか:とかの意味がわからんとか,使い方を知らネいうレベルは論外
  2. 三項演算子は,あくまで評価式ということと,2個目と3個目の取れる型の組み合わせを覚えておけば,コンパイルエラーがでても焦らない.
  3. ネストは避ける.もしくは,括弧をつける

ということです.はい.

*1:それらが,評価結果の型(この場合はObject)に対して代入可能であるかどうかは関係がない.