JEP 286導入に関する提案が,platform-jep-discussメーリングリストに提出された。実装されれば,Javaの型推論がローカル変数にまで拡張されることになる。提案はまだ初期の段階のため,どのバージョンを対象とするか,あるいは実装されるかどうかも定かではない。
型推論とは,型の関連付けをしない変数宣言を可能にする機能である。Javaでは少し前から型推論を備えている - Java 5でジェネリックが追加された時に,ジェネリックメソッドを扱う型推論が採用された。Java 7ではダイアモンド演算子<>
が(Project Coinの一部として)導入されて,ArrayList<>
にバインドされた型を使用せずにList<String>
型の変数を初期化できるようになった。さらに最新のJava 8では,メソッドチェーンの型を推論するラムダ式とストリーム,ラムダ引数の仮パラメータ型が追加されている。型に関する情報は,多くの場合,周囲の文脈やイニシャライザ(initializer)で使用される式から推論することが可能だ。同じ理由で,型を持たない式(0
やnull
のように)については,必ずしも正しい型を推論することはできない。Java言語仕様では,18章すべてを型推論の説明に割いている。
実質的にfinalなローカル変数の型推論を含む,型推論のサポートがすでに存在していることから,ローカル変数全般が対象であると理解しても大きな飛躍ではない。今回の提案はローカル変数(メソッドないしラムダ本体内で定義された変数)のみを対象とするもので,メソッドシグネチャやフィールドシグネチャは適用外である。
提案では,型推論を使用する変数を宣言するために,var
コンストラクトをキーワード的に使用する。型推論を備えた言語では,型定義を変数名の後に置いて,変数ないしパラメータをaNumber:Int
あるいはaNumber
と定義することで,型定義(:Int
)を省略可能なサフィックスとして効率よく扱えるようにするのが一般的だ。しかしながらJavaは,型を先頭に置くCなどの言語をベースとしており,これを変更するというのは現実的ではない。そこで,‘任意の型’を表すプレースホルダとしてvar
をキーワード的に使用するという,他の言語で変数を定義する場合と同じような方法を採用したのだ。これによって次のような文の記述が可能になる。
var proposal = "JEP-286";
この場合の変数proposalの型は,もう一方の式の具体的な型からStringと推定される。この方法を使えば,次のような総称型データ構造も単純化することが可能だ。
var phonebook = new HashMap<String,String>()
型の推論結果が具象型になる点には注意が必要だ。この場合であれば,インターフェースを使用する方が望ましいだろう。ただし,ローカル変数のみが対象であることを考慮すれば,ほとんどの目的において,その区別に特段の意味はないはずだ。
その他のキーワードライクなコンストラクト,例えば読み取り専用を表すものなどにメリットはないのか,という疑問もある。final var
を使用することは可能(finalを有効にする推論は現在でも可能だが,それが必要な場面はないだろう)だが,const
やval
,let
など,他の言語にインスパイアされた使い方も考えられる。var宣言にはauto
などの別案もあるため,JEP提案者はフィードバックを求めている。どの案が望ましいか意見を求めるための調査も実施中だ。
推奨実装では,識別子としてvar
を使用している既存のJavaプログラムが使えなくなる点に配慮して,var
(あるいはauto/let/def/val
...)を新たな予約語とはせず,Object
やString
のような型名として,実質的な予約語とすることにしている。var
を型(クラス
ないしインターフェース
)の名前に使用している既存アプリケーションには問題が発生するが,そのような命名はそもそもJavaのガイドラインから逸脱している。
実装済みのプロトタイプを使って既存のJDKソースコードを一通り調査した結果からは,ほとんどのローカル変数について,問題なくvar
を使用するように変更が可能だった。正常な推論ができなかったいくつかの例では,イニシャライザの値がない,イニシャライザがnull
である(当然ながらこの場合は,型が特定されない),指定されたものよりも厳密な型に推論された(List
ではなくArrayList
に推論された等)といった理由があった。この結果は,今回の提案が現実的に実施可能なアイデアであり,多くの場合において有効であることを示している。
JDKソースコードを対象としたプロトタイプの実行結果:
- ソースコード内に存在する正確な型が推論された – 83.5%
- 受容可能な異なる型(一般的にはより厳格な型)が推論された – 4%
- 推論された型が無効なためリジェクトされた – 0%
- イニシャライザがないためリジェクトされた – 8.5%
- イニシャライザがnullのためリジェクトされた – 3%
- 対象となる型が必要なためリジェクトされた – 0.5%
イニシャライザが指定されていない場合とnullの場合を除けば,99%のローカル変数の型推論が可能であること,95%がソースコードに存在する正確な型が推論されていることが分かります。
実質的にfinalなローカル変数(全ローカル変数の77%)の場合:
- ソースコード内に存在する正確な型が推論された – 86%
- 受容可能な異なる型(一般的にはより厳格な型)が推論された – 4.5%
- 推論された型が無効なためリジェクトされた – 0%
- イニシャライザがないためリジェクトされた – 8%
- イニシャライザがnullのためリジェクトされた – 0.5%
- 対象となる型が必要なためリジェクトされた – 0.5%
この機能をJava言語の将来バージョンに追加する提案は,JEP 286のタイトル下で議論される予定である。意見があれば,2016年3月16日の締め切りまでにアンケートに記入することで,Javaチームにフィードバックすることが可能だ。
最新情報として,JEP 286のこれまでの作業成果を開発者が試すことのできるように,London Java CommunityとIteratr LearningのRichard Warburton氏が,JEP 286をサポートするOpen JDKの非公式ビルドを公開している。これまで説明したような新機能の確認や試行が簡単にできるようになる。
この記事を評価
- 編集者評
- 編集長対応