BT

最新技術を追い求めるデベロッパのための情報コミュニティ

寄稿

Topics

地域を選ぶ

InfoQ ホームページ ニュース Javaの型推論は変更可能性の仕様をサポートしない

Javaの型推論は変更可能性の仕様をサポートしない

原文(投稿日:2016/12/22)へのリンク

Javaの型推論は、 開発者が変数の明確な型をvarキーワードで置き換えられるよう提案されたJavaの機能であるが、ミュータブルな変数とイミュータブルな変数を区別するキーワードをサポートしない予定である。最近のやり取りが示すようにコミュニティ内でこれをどのように実装すべきであるか合意を欠いているためだ。イミュータブルな変数のために提案された選択のいくつかはvalletを含む。また、込み入ったケースに長く議論することを防ぐために、このようなケースのいくつかは簡潔にするために除外される予定である。JEPは対象バージョンを示していないが、Java 10の可能性が高いだろう。

JEP 286のスコープを完全に定義するための一連の提案と協議のあと、オラクルのJava言語アーキテクトであるBrian Goetz氏は次のことに言及した。ローカル変数の型を推論する新しい機能の実装(と明示的に型を示しているなら儀式を避けること)における重要な合意があり、そのような機能はvarというキーワードを使うべきであるということである。これに加えて、コミュニティはまたScalaやKotlin、JavaScriptがしているような他言語と同様の方法でミュータブルとイミュータブルの推論を区別したいという彼らの要望を強調した。しかし、これが有益な機能であるという同意がある一方で、この区別をどのように実装すべきかについては一致はない。var/valvar/let(raw type)/varそれぞれに強く賛成する人と強く反対する人がいるからだ。この議論で型推論の状況が遅れることを避けるために、機能のリーダは単純にローカル変数の型を推論することまでスコープを縮小することを決めた。変更可能性の区別については考慮から外した。これにもかかわらず、イミュータブルなローカル変数の型はfinal varというわずかに長い構文だけれども、まだ推論される。

var s = "hello"; // type of s is String
var keys = map.keySet(); // assuming map is of type Map<K, V>, type 
                         // inferred for keys will be Set<K>
final var MAX_COUNT = 100L; // MAX_COUNT will be immutable long

更新は変更可能性の拡張に気づかせるためにも使用された。一方では、変数の型を推論するために使うのは初期化情報だけとなるだろう。これは次のことを意味する。宣言されるときに初期化されない変数は明示的に型を必要とするだろうということだ。けれども、それはまた潜在的にわかりにくいエラーをいくつか防ぐ手助けとなるだろう(コードの深いところで変数に何かが起こるために誤った型が推論されるのような場合など)。もう一方では、ローカル変数だけが型推論可能で、フィールドやメソッドは除外する。これは、それらにはクラスのパブリックなインタフェースの一部があり、それゆえにプログラマによって明示的に宣言される必要があるという仮設に基づく。型推論が動作しない他のケースは、それら自身の型を推察することを示す初期化の式である。たとえば以下のようなものだ。

List<String> list = new LinkedList<>(); // type not indicated in
                                        // initialisation, but inferred
                                        // from variable declaration
var list = new LinkedList<>(); // error, impossible to infer a type for
                               // the contents of the list

Function<String, Integer> f = s -> s.length(); // type of s and length
                                               // inferred from
                                               // declaration
var f = s -> s.length(); // error, type of s unknown, return type of
                         // length unknown

int[] array = {1, 2, 3}; // 1, 2, 3 interpreted as integers
var array = {1, 2, 3}; // error, poly expressions not supported
                       // (see below)

// Use Integer.valueOf(int)
Function<Integer, Integer> intFunction = Integer::valueOf;

// Use Integer.valueOf(String)
Function<String, Integer> stringFunction = Integer::valueOf; 

// error, ambiguous initialisation
var function = Integer::valueOf; // unable to know which overloaded
                                 // version of valueOf should be used

ここでは上記のはっきりしたサブケースがサポートされるか否かがはっきりしない。Goetz氏が言うように、"私たちはイニシャライザをスタンドアロンの式として扱い、その型を得ることで変数の型を得ています。配列のイニシャライザ、ラムダやメソッド参照のようなものですが、それらは*多相的な式*です。[...] そのためそれらは除外されます。". 多相的な式(Poly式)はJava 8でラムダとともに導入された概念で、それらの型は算出される点で普通の式とは異なる。普通の式では、型はコンパイル時に式の内容を調べることで得ることができる。一方Poly式は対象の型も必要とする(すなわち式が割り当てようとしている変数の型である)。型を算出するためだ。これは次のことを意味する。Poly式はすでにそれら自身の何らかの型推論とPoly式の型推論を試みることはとても困難もしくは不可能であるかもしれないことを示すということだ。しかしこのカテゴリに適合するいくつかのシナリオがあるが、適切な型推論のための十分な情報を提供するように思え、将来において含めることが考慮されるかもしれない。

var a = {1, 2, 3}; // could infer type int[]
var f = (String s) -> s.length(); // could infer type
                                  // Function<String, Integer>

その限界にもかかわらず、ローカル変数の型推論はJavaと他のJVM言語のギャップを縮小する手助けをするように見える。Javaプログラマにはボイラープレートを減らす。そして、ラムダが今追加の機能性とともに拡張されるのと同じ方法で、この最初のバージョンの後に型推論は改善されるかもしれない。これはJVM言語の非公式の力学が新しい機能の実験場として働くことを裏づけるだろう。もっとも一般的なものは最後にはJavaに導入されるのだ。

Rate this Article

Relevance
Style

この記事に星をつける

おすすめ度
スタイル

BT