null 制限型と null 許容型
(bugs.openjdk.org)Null-Restricted and Nullable Types (Preview)
概要
Java の型に対して、null を許容するか拒否するかを示す nullness マーカーをサポートするプレビュー言語機能。
目標
- Java の参照型を改善し、プログラマーが null 参照を想定しているかどうかを表現できるようにする
- nullness 属性が異なる型の間の変換をサポートし、不適切に扱われた null 値に対する警告を提供する
- 既存の Java コードとの互換性を保ち、新機能を段階的に導入できるようにする
- null を拒否する型の変数が、最初に読み取られる前に初期化されることを保証する
- 別個にコンパイルされたクラスでも、null を拒否する型を実行時に強制する
- 実行時最適化に必要なメタデータと完全性保証を提供する
非目標
- 既存コードを自動的に再解釈しない
- すべての null 値を明示的に処理することを要求しない
- プリミティブ型に対する変更は含まない
- 標準ライブラリに言語改善を適用しない
動機
- Java プログラムでは、String 型の変数は String オブジェクト参照または null 値を持ちうる
- 変数が null を許容するかどうかを明確に表現できず、混乱やバグの原因になる
- 開発者が null 値をサポートしないのか、あるいは想定しているのかを、型の一部として明示できる手段が必要である
説明
nullness 属性とマーカー
- 参照型は nullness を任意で表現できる
Foo!は null を含まない null-restricted 型Foo?は null を含む nullable 型- 既定では
Fooの nullness は指定されない
フィールドと配列の初期化
- null-restricted フィールドや配列は、使用前に必ず初期化されなければならない
- 初期化されていない null-restricted フィールドを読み取ろうとすると、例外が発生する
式の nullness と変換
- Java コンパイラはすべての式の nullness を決定する
- nullness 変換により、nullness が異なる式を扱える
- narrowing nullness 変換は、実行時に NullPointerException を発生させる可能性がある
実行時 null チェック
- narrowing nullness 変換が発生すると NullPointerException が発生する
型変数の nullness
- 型変数も nullness を表現できる
- null-restricted と nullable の型変数は、ジェネリックコード内で特定の nullness を主張する
型引数と境界
- 型引数は nullness を表現でき、これは API の nullness に影響する
- nullness が一致しない型引数は警告を発生させる可能性がある
メソッドのオーバーライドと型引数推論
- nullness は、メソッドシグネチャが同一かどうかを判断する際には無視される
- オーバーライドメソッドの戻り値型は、nullness 変換によって変換できる
コンパイラ警告
- null-restricted 型を作成すると、新たなコンパイル時エラーが発生する可能性がある
- narrowing nullness 変換、null-hostile な演算での
?型の使用などは警告を発生させる可能性がある
コンパイルおよびクラスファイル表現
- ほとんどの null マーカーはクラスファイルから除去される
- 新しい NullRestricted 属性は、フィールドが null 値を許容しないことを示す
コアリフレクション
Foo!.classやFoo?.classリテラルは存在しない- 新しい RuntimeType API は、実行時に null-restricted バリアントを記述する
補足的な変更
- 従来のシリアライズは null-restricted フィールドおよび配列と互換性がない
- javadoc は nullness マーカーを含む
- java.lang.reflect.Type および javax.lang.model API は nullness をエンコードする
代替案
- Java エコシステムのさまざまな開発ツールは、独自に null 追跡を実装している
- 他のプログラミング言語は、型システム内で nullness を追跡している
- 実行時の nullness 強制は、明示的なチェックや Objects.requireNonNull の呼び出しで実装できる
依存関係
- Flexible Constructor Bodies (Second Preview) が必要
- Null-Restricted Value Class Types (Preview) や JEP 402: Enhanced Primitive Boxing (Preview) などの将来的な作業
GN⁺のまとめ
- この JEP は、Java で null 値を明確に扱うための手段を提供し、コードの安定性と可読性を高める
- null-restricted 型と nullable 型を導入することで、null 参照によるバグを減らせる
- 既存コードとの互換性を保ちながら段階的に導入できるため、開発者に柔軟性を提供する
- 他言語との比較において、Java の null 処理能力を強化できる
- 類似機能を提供するツールとしては、Kotlin の null-safety 機能がある
1件のコメント
Hacker Newsの意見
C#とKotlinのnull処理方式の比較
lateinit var宣言によって、初期化されていないnon-nullable変数を後で初期化できる機能を提供する新しい提案についての意見
nullness-narrowingの自動変換に対する懸念
すべての変数をデフォルトでnon-nullとして示す方法の必要性
Javaで言語レベルの明示的なoptionality機能が必要
標準ライブラリに言語改善事項を適用しないという決定への批判
コンパイル時警告をエラーへ昇格させる簡単な方法の必要性
デフォルトでnon-nullable、immutable、狭いスコープに設定すべき必要性
Hack言語でのnull処理経験
Java SDKにこの機能を適用できるのかという質問
関連リンク