プログラムdeタマゴ

nodamushiの著作物は、文章、画像、プログラムにかかわらず全てUnlicenseです

JavaのOptionalは現状失敗作

 チマチマとは書いていたんですが、1年ぶりぐらいに真面目にJava書いています。

 前からずっと思っていて、実際何度か口にしたことがあるんですが、やっぱ言いたい。

 JavaのOptionalは失敗作

 

 

JavaのOptionalの何が悪いの?

 言語機能じゃないから。完全にここに集約されると私は思っています。

 Java8で登場したOptionalですが、この時にコンパイラを拡張しなかったのがそもそもの問題だと思っています。

 

AutoBoxing

 例えばKotlinのnullableのような機能の導入、というのは慎重になるべきでしょうし、すぐできるとは思えません。

 しかし、Optionalへのオートボクシングぐらいは実現できたのではないでしょうか?int→Integerというオートボクシングは既に存在しているわけで、最初から導入すべきだったと思います。

public OptionalInt  intMethod(){
     if(何か条件) return 1;  // -> OptionalInt.of(1)に
     if(何か条件) return OptionalInt.of(1);  // そのまま
     return null;// -> OptionalInt.empty()に
}

public Optional<Object> objMethod(){
    Object obj = null;
    if(何か条件)   return new Object(); //-> Optional.of(new Object())に
    if(何か条件)   return obj; // -> Optional.ofNullable(obj)に
    return null; // -> Optional.empty()に
}

 

 実に鬱陶しいofやらemptyやらofNullableが省略できる上、Optionalの癖にnullが返せるという謎の状況も生まれにくいでしょう。(※上の例だと、OptionalIntをそのまま返すとしてるけど、ここでnull挿入できる)

 むろん、色々な議論があったのでしょうが、導入が許されるのは、最初だけなのです。オートボクシングはもはや、実現不可能です。

 なぜなら、現在、nullが返せるという謎の状況が合法だからです。(どれほどおかしいとしても!)

public Optional<Object> objMethod(){
    return null;
}

 オートボクシングを認めてしまうと、後方互換を破壊してしまいます。

 今から可能なのは、Kotlinの様に言語機能を拡張するか、後方互換の破壊か、nilとかnullに変わる単語を導入する(ミスる自信があるぞ!)か、アノテーションで処理変えるか、Optionalに暗黙に変換されるOptional2見たいな型でも用意するかぐらいでしょうか。

 

Auto-Unboxing

 Optionalのオートボクシングを認めるなら、当然、アンボクシングもあるべきです。Optional<T>→Tへのアンボクシング………の前にOptional→booleanへのアンボクシングです。アンボクシングと言うよりは、暗黙の変換ですね。

 例えば、以下の様な状況を考えると、二つ目のif文の方が読みやすいと思います。isPresentって長いし面倒くさいよ。

if(intMethod().isPresent()){
  //戻り値は特に使わない処理
}else{
}

if( intMethod() ){
  //戻り値は特に使わない処理
}else{
}

 

 ifPresentOrElseがあるだろ、この馬鹿たれ!というお叱りの声が聞こえますが、本気でそれが読みやすいと思っています?

 ifPresentOrElse(()->{},()->{})より、単純にif文の方が、私には読みやすいです。

 そして、条件式がOptionalだったら、trueの場合は_にアンボクシングした結果が格納される、みたいな構文でアンボクシングされると良いかなーとか思います。

int value = intMethod() ? _  :  0 ;
if( intMethod() ) {
  int x = _ + value;
}

 なるべくキーワードを増やさない様に_ってかいたけど、$1とか$2でもいいかもね。

 ifPresentOrElseなんかよりずっと読みやすいし、ラムダ式の変数のキャプチャとかも発生しない。

 更に推し進めて、存在演算子が導入されても良いと思います。

int value =  intMethod()? 0;

 

まとめ

 JavaもプリミティブのラッパーやString、列挙体、Cloneable、AutoCloseableなど、幾つかのクラスでは言語的に特殊処理しているのだから、Optionalは何が何でも絶対駄目という理由はないと思います。むしろ言語として特殊扱いすべきだったと思います。

 C++は難しすぎる、Javaの方が簡単と言われますが、OptionalはC++の方が簡単ですね。オートボクシングやbooleanへの変換は、C++では暗黙の型変換で普通に使えます。

 最近のJavaは言語機能の拡張に積極的ですから、早いところ、言語機能に組み込んで欲しいな。