回答編集履歴

3

append link

2016/08/12 02:38

投稿

yohhoy
yohhoy

スコア6189

test CHANGED
@@ -110,7 +110,7 @@
110
110
 
111
111
 
112
112
 
113
- **追記:** 仮に`Illegal<T>`クラスのコンパイルを通した場合、下記相当するバイトコードに展開されるでしょう。
113
+ **追記:** 仮に`Illegal<T>`クラスのコンパイルを通した場合、型消去により下記相当バイトコードに展開されるでしょう。
114
114
 
115
115
  ```
116
116
 
@@ -126,7 +126,7 @@
126
126
 
127
127
  ```
128
128
 
129
- ジェネリクス型の利用側ソースコードは次のようなるでしょうが、
129
+ ジェネリクス型の利用側ソースコードは次のようなるでしょうが、
130
130
 
131
131
  ```
132
132
 
@@ -136,7 +136,7 @@
136
136
 
137
137
  ```
138
138
 
139
- 生成されるバイトコードは下記に相当します。しかし、ジェネリクスに指定した型パラメータ(`T = Number`)に関係なく`num.create()`は常に`Object`型インスタンスを返すため、`Number`型へのキャストは常に失敗し`ClassCastExcetion`例外がスローされるという危険かつ無意味な処理が行われます。このため、Javaコンパイラはのコードをエラーとして扱います。
139
+ 生成されるバイトコードは下記に相当します。ジェネリクスに指定した型パラメータ(`T = Number`)に関係なく`num.create()`は常に`Object`型インスタンスを返すため、`Number`型へのキャストは常に失敗し`ClassCastExcetion`例外がスローされるという危険かつ無意味な処理となっています。このため、Javaコンパイラは`Illigal`クラスようなソースコードをエラー扱います。
140
140
 
141
141
  ```
142
142
 
@@ -145,3 +145,5 @@
145
145
  ```
146
146
 
147
147
 
148
+
149
+ Javaのジェネリクスで実際に何が行われるかを深く理解したければ、[Java Generics FAQs - Under The Hood Of The Compiler ](http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html) をお勧めします。

2

append

2016/08/12 02:38

投稿

yohhoy
yohhoy

スコア6189

test CHANGED
@@ -106,4 +106,42 @@
106
106
 
107
107
 
108
108
 
109
- `T`のコンストラクタを呼び出すコード、つまりジェネリクス型`Illegal`クラスのバイトコード中には、型消去により「実際に指定された型」情報が既に失われています。のためインスタンス生成は不可能です。
109
+ `T`のコンストラクタを呼び出すコード、つまりジェネリクス型`Illegal`クラスのバイトコード中には、型消去により「実際に指定された型」情報が既に失われています。のため、ジェネリクス型を作成したプログラマが期待する動作「`create`メソッド中で`T`型としてインスタンス生成する」ことは不可能であり、Javaコンパイラはこのソースコードをエラーとして拒絶します。
110
+
111
+
112
+
113
+ **追記:** 仮に`Illegal<T>`クラスのコンパイルを通した場合、下記に相当するバイトコードに展開されるでしょう。
114
+
115
+ ```
116
+
117
+ class Illegal {
118
+
119
+ public Object create() {
120
+
121
+ return new Object();
122
+
123
+ }
124
+
125
+ }
126
+
127
+ ```
128
+
129
+ ジェネリクス型の利用側ソースコードは次のようなるでしょうが、
130
+
131
+ ```
132
+
133
+ Illegal<Number> num = new Illegal<Number>();
134
+
135
+ Number n = num.create();
136
+
137
+ ```
138
+
139
+ 生成されるバイトコードは下記に相当します。しかし、ジェネリクスに指定した型パラメータ(`T = Number`)に関係なく`num.create()`は常に`Object`型インスタンスを返すため、`Number`型へのキャストは常に失敗し`ClassCastExcetion`例外がスローされるという危険かつ無意味な処理が行われます。このため、Javaコンパイラはこのコードをエラーとして扱います。
140
+
141
+ ```
142
+
143
+ Number n = (Number) num.create();
144
+
145
+ ```
146
+
147
+

1

refine

2016/08/12 01:50

投稿

yohhoy
yohhoy

スコア6189

test CHANGED
@@ -24,7 +24,7 @@
24
24
 
25
25
 
26
26
 
27
- 技術的に正しくありません。「コンパイル時に型情報が消える」の意味を誤解しているように見うけられます。
27
+ 技術的にはあまり確ではありません。「コンパイル時に型情報が消える」の意味を誤解しているように見うけられます。
28
28
 
29
29
 
30
30
 
@@ -44,7 +44,7 @@
44
44
 
45
45
 
46
46
 
47
- なりません。getメソッド戻り値は`Number`型であり(型消去結果)、呼び出し側に`Integer`型へのキャスト処理が(コンパイラにより自動的に埋め込まれます。
47
+ なりません。型消去の結果としてJVMから見えるgetメソッド戻り値は`Number`となっています。一方の呼び出し側では、コンパイラより`Integer`型へのダウンキャスト処理が自動的に埋め込まれており、JVMはこれに従って`Number`→`Integer`へと変換します(コンパイル時に型検査済みのため、このダウンキャストは必ず成功する)
48
48
 
49
49
 
50
50
 
@@ -106,4 +106,4 @@
106
106
 
107
107
 
108
108
 
109
- `T`のコンストラクタを呼び出すコード、つまりジェネリクス型`Illegal`クラスのバイトコード中には、型消去により「実際に指定された型」情報が既に失われています。このためインスタンス生成不可能です。
109
+ `T`のコンストラクタを呼び出すコード、つまりジェネリクス型`Illegal`クラスのバイトコード中には、型消去により「実際に指定された型」情報が既に失われています。このためインスタンス生成不可能です。