Javaでは、配列を型変数のバインドにできないのに、ワイルドカードのバインドにできるのはなぜですか?
あなたが持つことができます:
List< ? extends Integer[] > l;
しかし、あなたは持つことができません:
class MyClass< T extends Integer[] > { } // ERROR!
なんで?
Javaでは、配列を型変数のバインドにできないのに、ワイルドカードのバインドにできるのはなぜですか?
あなたが持つことができます:
List< ? extends Integer[] > l;
しかし、あなたは持つことができません:
class MyClass< T extends Integer[] > { } // ERROR!
なんで?
次の Java コードを検討してください。
package test;
public class Genric<E>
{
public Genric(E c){
System.out.println(c.getClass().getName());
}
public static void main(String[] args) {
new Genric<Integer[]>(new Integer[]{1,2});
}
}
最初のケースの場合:
List< ? extends Integer[] > l;
このようなことをするとList< ? extends Integer[] > l;
、Java コンパイラはそれを として認識し、 List< ? extends Object> l;
それに応じて変換します。これが、エラーが発生しない理由です。
生成されたバイトコードは次のとおりです。
.
.
.
20: aastore
21: invokespecial #52; //Method "<init>":(Ljava/lang/Object;)V
24: return
.
.
行番号21をチェックアウトします。java.lang.Integer
ただし、 ;の配列を渡しました。内部的には に変換されjava.lang.Object
ます。
2 番目のケースの場合:
class MyClass< T extends Integer[] > { } // ERROR!
Java言語仕様に従って:
TypeParameter:
TypeVariable TypeBoundopt
TypeBound:
extends ClassOrInterfaceType AdditionalBoundListopt
.
.
ご覧のとおり、境界はクラスまたはインターフェイスのみで構成されています (プリミティブ型でさえありません)。したがって、このようなことを行うclass MyClass< T extends Integer[] > { }
とInteger[]
、クラスまたはインターフェイスとしての資格がありません。
私のJava仕様の理解によると、これは次のようなすべてのシナリオを解決するために行われました
class MyClass< T extends Integer[] >
class MyClass< T extends Integer[][] >
class MyClass< T extends Integer[][]...[] >
java.lang.Object
例のように、それらのすべてをパラメーターとして渡すと、として表すことができるためです。
public Genric(E c){
System.out.println(c.getClass().getName());
}
「c」はその真の型を記憶しているためです。
これが役立つことを願っています。
これが禁止されるべき特定の理由について考えようとしていますが、私が考えることができる唯一の理由は、それが完全に不要な構造であるということです。
class Foo<T extends Integer[]> {
T bar();
}
と同等です
class Foo<T extends Integer> {
T[] bar();
}
明らかに、ワイルドカードのケースについては同じことが言えません。したがって、そこでは許可されています。
次のようなことができます:
public class MyClass<K> {
K array;
public MyClass(K k) {
array = k;
}
または、次のようなこともできます。
class MyClass< T extends Integer > {
...make your variable MyClass[]...
}
これが役に立てば幸いです。私はあなたが求めていたものからそれほど遠くありません.