2011年8月1日

Java7 のダイアモンドオペレータと型推論について。

『Java7 ジェネリクスのダイアモンド・オペレータ』プログラマーの脳みそ(http://d.hatena.ne.jp/Nagise/20110729/1311950039) で解説されている内容から派生した、Java のジェネリクスや型推論まわりの話など。 ・・・話のレヴェル高いお(´Д` )
15
Kota Mizushima (on a diet) @kmizu

http://bit.ly/n09Sre ちょっとこれを読んで思った事。newするときに、 new ArrayList<? extends String>(); ができないのは、自然というか当然のように #java

2011-07-31 15:31:24
Kota Mizushima (on a diet) @kmizu

思っていた。というのは、? extends Stringなんて型は、「ファーストクラスの型としては」存在しないから。というのが1点。あと、new java.util.ArrayList<? extends String>(); って一体何をnewしたいのかって話がある。

2011-07-31 15:35:05
Kota Mizushima (on a diet) @kmizu

よく誤解されるところではあるんだけど(これは、@nagise さんに言っているわけではありません)、? extends Stringの、?は、ジェネリックスの実型引数における「修飾子」のようなものであって、それ自体は型を構成しない。

2011-07-31 15:37:07
Kota Mizushima (on a diet) @kmizu

つまり、 ? extends String f = null; とかこんな事はできないよね、って話。(? extends T)は「型ではない」というのが重要。

2011-07-31 15:38:51
Kota Mizushima (on a diet) @kmizu

、さっきのもう一つの方の話。さて、new java.util.ArrayList<? extends String>()が仮にできたとして、これは一体何を意図しているのだろうか?「Stringのサブタイプの内どの型が入っているかわからないコンテナ」ということになるだろうけど、

2011-07-31 15:43:35
Kota Mizushima (on a diet) @kmizu

これが仮にできたとして、実際にはまず役に立たない。このnewしたnew java.util.ArrayList<? extends String>();に対してできる操作は、add(null); とかdeteleとかget系くらいしかないので、無理やりキャストでもしない限り

2011-07-31 15:45:25
Kota Mizushima (on a diet) @kmizu

あと、"これ、どうなってるかというと、Javaのジェネリクスはイレイジャ方式なのでなんか適当にnew ArrayList()しちゃってるようです。" 実装としてはそうですが、diamond operatorの意味としては、new ArrayList<String>();を推論

2011-07-31 16:03:20
Kota Mizushima (on a diet) @kmizu

してないとまずい気がする。diamond operatorの趣旨は、あくまで推論することであって、無検査キャストを通すようなものではないはずなので。この辺、正式な仕様書があればはっきりするんだけど…。

2011-07-31 16:05:54
Kota Mizushima (on a diet) @kmizu

この辺の仕様(というには未定義部分が多過ぎるが) file:///C:/Users/Mizushima/Downloads/enhancements-1_0-final-eval-spec/# 読む限りでは、やっぱり

2011-07-31 16:10:23
Kota Mizushima (on a diet) @kmizu

Stringとかその辺りの型パラメータが推論されるはず。 "In both cases, the compiler infers Object as the value of type argument for the constructor. " と書いてるわけだし。

2011-07-31 16:11:43
Kota Mizushima (on a diet) @kmizu

間違えてローカルへのリンク貼ってしまった。JSRのSpecは http://bit.ly/nXPEhV の方。

2011-07-31 16:12:54
Kota Mizushima (on a diet) @kmizu

diamond operatorの趣旨は、仕様に "the diamond syntax is used to mark locations where type inference is requested" 書かれてる。要は<>の部分の型を推論してくださいね、という。

2011-07-31 16:28:20
Kota Mizushima (on a diet) @kmizu

あー、なるほど。diamond operatorは、基本的にJSR3rd の 15.12.2.7と15.12.2.8における型パラメータ推論規則を使うためのシンタックスシュガーのようなものとと考えて、おおむね間違い無さそう。

2011-07-31 16:33:26
Kota Mizushima (on a diet) @kmizu

http://bit.ly/qtMAD6 …Javaレベルでのループはバイトコードではジャンプ命令に変換されるわけでありまして…。バイトコードでジャンプ命令使ったって、VM側からループと認識されたらそれで終わりのような…。というか、単にわかっててネタで言ってるだけだよね。

2011-07-31 17:06:46
なぎせ ゆうき @nagise

@kmizu んー。raw型がすべてを受け入れるのに対し、推論が必要なところをマークするという話ですよね。そこから「推論しろ」というのはちょっと飛躍に思えるなあ

2011-07-31 23:54:04
Kota Mizushima (on a diet) @kmizu

@nagise おっしゃる通り、その文だけだと飛躍に見えても仕方無いかもしれません。しかし、仕様書を見ると、はっきりと

2011-08-01 00:27:59
Kota Mizushima (on a diet) @kmizu

@nagise "In both cases, the compiler infers Object as the value of type argument for the constructor." と書いてあるわけです。

2011-08-01 00:28:59
なぎせ ゆうき @nagise

@kmizu たしかに書いてはありますね。んー。ただこの例がアレでちょっとなあ。raw型と<?>の場合ですよね…。inferとは書かれているけど。

2011-08-01 00:31:48
Kota Mizushima (on a diet) @kmizu

@kmizu "both cases" というのは、List rawList = new ArrayList<>(); List<?> wildList = new ArrayList<>(); の両方を指していますよね。つまり、左辺に境界無しワイルドカードが来た場合

2011-08-01 00:30:02
Kota Mizushima (on a diet) @kmizu

@nagise つまり、 List<?> wildList = new ArrayList<>(); のときに、 List<?> wildList = new ArrayList<Object>(); に推論されるという話なわけで、境界付きワイルドカードだけ特殊だと考えるのは

2011-08-01 00:31:12
Kota Mizushima (on a diet) @kmizu

@nagise ちょっと難しいのではないかと。あと、型の推論結果について、"This result is implied by the rules contained in §15.12.2." というのも見逃してはいけないポイントかと。

2011-08-01 00:32:16
なぎせ ゆうき @nagise

@kmizu んー。僕の目下の疑問は、その「推論」が不可視である点なんです。推論が行われていようと、実は行われていなかろうと、それを観測できないんですよ。

2011-08-01 00:33:05
Kota Mizushima (on a diet) @kmizu

@nagise なるほど。つまり、推論が行われていることを観測できる事を示せばいいと。

2011-08-01 00:38:55
なぎせ ゆうき @nagise

言語仕様が見つかった。 15.12.2コンパイル時のステップ2:メソッド・シグネチヤの決定

2011-08-01 00:37:03
残りを読む(72)

コメント

コメントがまだありません。感想を最初に伝えてみませんか?