回答編集履歴
3
append link
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
|
-
生成されるバイトコードは下記に相当します。
|
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
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
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メソッド
|
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`クラスのバイトコード中には、型消去により「実際に指定された型」情報が既に失われています。このためインスタンス生成は不可能です。
|