JDK 11の採用数は日を追って増えており、2021年末にはJDK 8と肩を並べるまでになった。
Hanno Embregts氏は、Devoxx UKの観衆を前にした講演の中で、自身がOracle Java 11認定に向けて学ぶ中で知った、11のおかしな点を紹介した。10年半近いキャリアの裏側には、このようなJavaの奇妙な部分を解決すると同時に、以降の慣習として身に付けていく必要があったのだ。認定に向けて学ぶ上で最も重要なことは何か、と問われたEmbregts氏は、次のように返答した。
コーディングには自信があったのですが、プロフェッショナルな開発者としては、使用するツールの知識を高めるために時間を投資する必要がある、と感じました。そうすることで、生産性を改善できるのです。
開発者はコードを書いたり調べたりすることが好きなので、氏のプレゼンテーションは、注目する11のUTそれぞれに"パズル"を当てはめたスライドなしのプレゼンテーションになった。
- ローカル型推論と"[]"の組み合わせはコンパイルできない。
- C形式の配列定義は複製されないので、変数毎に複製する必要がある。
#10: ストリームのソートはComparableオブジェクトに対してのみ機能する
オブジェクトのストリームをソートする場合、ターゲットのオブジェクトがcompareTo(...)メソッドを実装したComparableオブジェクトでなければ、RuntimeExceptionがスローされる。
#9: インターフェース内の静的メソッドには、それを含むインターフェースのみがアクセス可能である
クラスから静的メソッドへのアクセスはコンパイルできない。
#8: enumの匿名サブクラスを作成して、その機能をオーバーライドする
enum内で定義されたメソッドをオーバーライドしない場合、予期しない動作が発生する可能性がある。目的とする効果を確実に達成するためには、匿名の内部クラスでメソッドをオーバーライドすることが可能であると同時に、そのようにする必要がある。
intあるいはlongを0で除算した場合には
ArithmeticExceptionがスローされるが、浮動小数点数(floatあるいはdouble)を使用した場合の結果はPOSITIVE_INFINITYになる。
#6: メソッドのオーバーロードパラメータの優先度は、使用する型によって異なる
正確な型が見つからない場合は、より広いプリミティブ型に拡張される。また、プリミティブの場合や型が不明の場合は、ボックス化プリミティブないしvarargsへのマッチが試みられる。
#5: Switch文で複数の case をまとめようとすると、分かりにくい結果を招く可能性がある
2つの異なる条件をまとめるために"|"を使うと、それがbit演算子として機能し、演算結果をswitchが適切なカテゴリに一致するように使用することによって、意外な動作をする場合がある。
#4: クローン配列、不変コレクション配列、不変数を扱う場合の等価性
Javaのクローン操作は浅い(shallow)ので、配列の場合には、最初の配列あるいはコレクションに含まれていた同じオブジェクトを示すようになる。この状況で、"=="を使用した2配列の比較にはfalseが返されるが、Object.equals(...)を使うとtrueが返される。
Javaは最適化のため、-128から127の範囲の数値をキャッシュしている。そのため、この範囲内の数値は、ボクシング時には常に同じリファレンスに解決されることになる。
Javaの関数インターフェースは、ただひとつのメソッドを持ち、@FunctionalInterfaceアノテーションを使用する必要がある。
要するに、毎日の通勤で車を運転していてもプロのドライバにはなれない、ということなのだ。毎日コーディングしているからといって、それでプロのコーダになれる訳ではない。この観点から言えるのは、中心的に使用しているフレームワークと言語の理解を深めるために時間を割く必要がある、ということだ。そうすることによって、記述するコードの品質を向上し、特定の操作によって生じる意外な結果に結び付いたトリッキーなバグを回避し、自身の生産性を高めることが可能になる。