In Java, why can't an array be a Type Variable's bound, but can be a Wildcard's bound?
Asked Answered
C

3

11

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?

Coinsurance answered 23/1, 2011 at 17:9 Comment(2)
It's a strange one. The JLS quite clearly states that you can only use classes or interfaces in type variables but fails to give any explanation whatsoever.Spectroscopy
just to do like-comparisons: "List< ? extends Integer[] > k1;" is allowed, but "List< T extends Integer[] > k2;" is not. But I couldnt find anything except null to add to the list! Eclipse says k1.get(0) returns type Integer[], but I could not add one.Taxaceous
U
7

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

  1. class MyClass< T extends Integer[] >
  2. class MyClass< T extends Integer[][] >
  3. ..
  4. 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.

Uncleanly answered 23/1, 2011 at 19:28 Comment(1)
+1 for digging into ther bytecode, although this still is more like a an explanation of "hows" rather than the "whys". Isn't the replacement of the type parameter with Object simply due to type erasure, and applied always? I.e. List<T extends MyClass> would also become a List<Object> in the bytecode isn't it? Generic type safety is checked only by the compiler before the type erasure happens.Riehl
S
3

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.

Spectroscopy answered 23/1, 2011 at 19:27 Comment(0)
V
0

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.

Vestryman answered 23/1, 2011 at 18:2 Comment(4)
I believe he asks "WHY" not "HOW TO ..." :(Diligent
Indeed. I'm not trying to use an array as a bound for T. Just wanted to know why this restriction is imposed.Coinsurance
Sorry for the misunderstanding, if you tell me how to delete this post I'll get rid of it since it's irrelevant.Vestryman
You don't see a "delete" link next to "edit"? Maybe you don't have enough reputation to delete posts...Coinsurance

© 2022 - 2024 — McMap. All rights reserved.