In Java, why can't an array be a Type Variable's bound, but can be a Wildcard's bound?
In Java, why can't an array be a Type Variable's bound, but can be a Wildcard's bound?
You can have:
List< ? extends Integer[] > l;
but you can't have:
class开发者_运维知识库 MyClass< T extends Integer[] > { } // ERROR!
Why?
Consider this Java code:
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});
}
}
For your first case:
List< ? extends Integer[] > l;
When you do something like this List< ? extends Integer[] > l;
then the Java compiler sees it as a List< ? extends Object> l;
and translates it accordingly. So this is why you don't get any error.
The generated byte-code is as follows:
.
.
.
20: aastore
21: invokespecial #52; //Method "<init>":(Ljava/lang/Object;)V
24: return
.
.
Checkout the line number 21. Although, I have passed an array of java.lang.Integer
; internally it is translated to java.lang.Object
.
For your second case:
class MyClass< T extends Integer[] > { } // ERROR!
As per java language specification:
TypeParameter:
TypeVariable TypeBoundopt
TypeBound:
extends ClassOrInterfaceType AdditionalBoundListopt
.
.
As you can see the the bound consists solely of class or an interface (not even primitive types). So when you do something like this class MyClass< T extends Integer[] > { }
then Integer[]
does not qualify as a class or interface.
As per my understanding of Java Spec, this was done to solve all the scenarios like
class MyClass< T extends Integer[] >
class MyClass< T extends Integer[][] >
- ..
class MyClass< T extends Integer[][]...[] >
Because all of them can be represented as java.lang.Object
and when passed as parameter, as in example
public Genric(E c){
System.out.println(c.getClass().getName());
}
as 'c' remembers its true type.
Hope this will help.
I'm trying to think about specific reasons this should be forbidden but the only one I can think of is that it's a completely unnecessary construct, because:
class Foo<T extends Integer[]> {
T bar();
}
is equivalent to
class Foo<T extends Integer> {
T[] bar();
}
Obviously the same cannot be said about the wildcard case, hence it's allowed there.
You can do something like:
public class MyClass<K> {
K array;
public MyClass(K k) {
array = k;
}
Or you could do something like this:
class MyClass< T extends Integer > {
...make your variable MyClass[]...
}
Hope this helps and I'm not too far off what you were asking for.
精彩评论