286

What's the reason why Java doesn't allow us to do

private T[] elements = new T[initialCapacity];

I could understand .NET didn't allow us to do that, as in .NET you have value types that at run-time can have different sizes, but in Java all kinds of T will be object references, thus having the same size (correct me if I'm wrong).

What is the reason?

Hearen
  • 6,019
  • 2
  • 36
  • 50
devoured elysium
  • 90,453
  • 117
  • 313
  • 521
  • 36
    What are you talking about? You can absolutely do this in .NET. -- I'm here trying to figure out why I can't do it in Java. – BrainSlugs83 Oct 05 '14 at 07:22
  • @BrainSlugs83 - please add a link to some code example or tutorial which shows that. – MasterJoe Apr 03 '20 at 22:57
  • Also see - https://stackoverflow.com/questions/21577493/why-not-create-an-object-and-cast-to-a-generic-type-whats-the-solution – MasterJoe Apr 06 '20 at 00:15
  • 1
    @MasterJoe2 the above code in the OP's question is what I'm referring to. It works fine in C#, but not in Java. -- The question states it works in neither, which is incorrect. -- Not sure there's value in discussing it further. – BrainSlugs83 Apr 06 '20 at 02:24
  • [Because it's a bug that hasn't been fixed yet. ](https://i.stack.imgur.com/hlOJI.jpg) – Meech Dec 11 '20 at 02:54

17 Answers17

219

It's because Java's arrays (unlike generics) contain, at runtime, information about its component type. So you must know the component type when you create the array. Since you don't know what T is at runtime, you can't create the array.

newacct
  • 110,405
  • 27
  • 152
  • 217
  • 29
    But what about erasure? Why doesn't that apply? – Qix - MONICA WAS MISTREATED Mar 05 '13 at 08:22
  • 17
    How does `ArrayList ` do it then? – Thumbz Mar 25 '14 at 23:55
  • 11
    @Thumbz: You mean `new ArrayList()`? Generic types do not contain the type parameter at runtime. The type parameter is not used in creation. There is no difference in the code generated by `new ArrayList()` or `new ArrayList()` or `new ArrayList()` at all. – newacct Mar 26 '14 at 00:05
  • 10
    I was asking more about how `ArrayList` works with its' `private T[] myArray`. Somewhere in the code, it must have an array of generic type T, so how? – Thumbz Mar 26 '14 at 01:02
  • 23
    @Thumbz: It doesn't have an array of runtime type `T[]`. It has an array of runtime type `Object[]`, and either 1) the source code contains a variable of `Object[]` (this is how it is in the latest Oracle Java source); or 2) the source code contains a variable of type `T[]`, which is a lie, but doesn't cause problems due to `T` being erased inside the scope of the class. – newacct Mar 26 '14 at 02:44
  • 1
    @Thumbz: yes, if you go with route #2 – newacct Mar 26 '14 at 08:43
  • @newacct How odd. Aren't references == pointers, which would mean they're all the same size (the size of an address)? If this is true, then the size should already be known, and if not, it seems you could just say something like `class CustomArray { TYPE [] myArray = new TYPE [42]; }` and it should be able to do exactly the same thing without giving any warnings. – Thumbz Mar 26 '14 at 09:24
  • 3
    @Thumbz: You can *access* array elements without any difference. But if you get the type of the array object itself, it will be wrong. For various reasons, Java arrays are reified (they know their component type at runtime), and `String[]` implies the array it points to actually has runtime component type `String` or subtype thereof, not just that it's an array that contains `String`s. It's been that way from the first version of Java, before Generics, and cannot be changed. – newacct Mar 26 '14 at 18:26
  • 1
    @newacct: I'm not totally sure I follow, but I still don't see why ` []` is a very different concept from `String []`. If you know at least one class from which TYPE inherits from, it seems that the compiler should be able to read `class la { T [] lala = new T[42]; }` and equivocate that to `{ Object [] lala = new Object[42]; }` – Thumbz Mar 27 '14 at 19:23
  • @Thumbz: In Java, `String[] foo = (String[])new Object[5];` is fine at compile time but causes an exception at runtime. It's just a historical fact of how arrays in Java were made that `String[]` and `Object[]` are two different classes at runtime. `new Object[42]` creates an object of runtime class `Object[]`, and it's not safe to consider that as `T[]` because if you have a method that exposes that to the outside of the class as type `T[]`, like `T[] getArray{ return lala; }`, and someone calls that on a `CustomArray` and assigns the result to a `String[]`, they will get an exception – newacct Mar 28 '14 at 04:48
  • If it causes an exception at run time, then how is it done in `ArrayList`? There must be some way of creating a `T[]` that doesn't cause exceptions. – Thumbz Mar 29 '14 at 18:26
  • @Thumbz: What makes you think there needs to be a `T[]`? Like I said, they could 1) have the variable of type `Object[]`, and cast to `T` when they get an element out of it, or 2) have the variable of type `T[]` but it's actually still of runtime class `Object[]`, and be careful not to expose it to the outside of the class. The two approaches are the same after erasure. – newacct Mar 29 '14 at 20:22
  • Why do you not know T at runtime? – committedandroider Dec 17 '14 at 23:48
  • @committedandroider: where would you get it from at runtime? – newacct Dec 18 '14 at 01:13
  • Say we have the List ADT, When the client initializes ArrayList(and runs the program), he or she does it by List list = new ArrayList ? Basically, you get when it is being used? – committedandroider Dec 18 '14 at 03:53
  • @committedandroider: Nope. That is exactly the same as `List list = new ArrayList();` – newacct Dec 18 '14 at 09:55
  • Oh so user doesn't have to specify type parameter when initializing? – committedandroider Dec 18 '14 at 18:20
  • @committedandroider: The user doesn't have to specify a type parameter, and specifying the type parameter doesn't change the compiled byte code. It's only used for compile-time type checking only. – newacct Dec 18 '14 at 19:12
  • The answer is not clear. In fact the topic need separate blog post to be explained. See my next comment. – Oleksandr Papchenko Nov 09 '16 at 12:16
  • The problem is deeper than pointed in that answer, so further investigation is needed. As you said type info is erased and in compiled code we have no difference between two generic types - all we have is base type - so why for T[] - compile to Object[]. In this case everything will be fine - array will remember that it was created with object type and will let save all types. However as for me the real problem is that arrays are covariant meaning that Animal[] can be assigned to Object[]. in other hand generics are not ArrayList can not be assigned to ArrayList – Oleksandr Papchenko Nov 09 '16 at 12:17
  • This is how i understand the topic at the time - that can be wrong. If you think this is wrong - please give me reference to the documentation or other source of truth :) – Oleksandr Papchenko Nov 09 '16 at 12:18
  • why do python do not have such problems ? – Rushikesh Jul 03 '20 at 14:55
140

Quote:

Arrays of generic types are not allowed because they're not sound. The problem is due to the interaction of Java arrays, which are not statically sound but are dynamically checked, with generics, which are statically sound and not dynamically checked. Here is how you could exploit the loophole:

class Box<T> {
    final T x;
    Box(T x) {
        this.x = x;
    }
}

class Loophole {
    public static void main(String[] args) {
        Box<String>[] bsa = new Box<String>[3];
        Object[] oa = bsa;
        oa[0] = new Box<Integer>(3); // error not caught by array store check
        String s = bsa[0].x; // BOOM!
    }
}

We had proposed to resolve this problem using statically safe arrays (aka Variance) bute that was rejected for Tiger.

-- gafter

(I believe it is Neal Gafter, but am not sure)

See it in context here: http://forums.sun.com/thread.jspa?threadID=457033&forumID=316

Community
  • 1
  • 1
Bart Kiers
  • 153,868
  • 34
  • 276
  • 272
  • 3
    Note that I made it a CW since the answer is not mine. – Bart Kiers May 28 '10 at 07:55
  • 11
    This explains why it might not be typesafe. But type safety issues could be warned by the compiler. The fact is that it is not even possible to do it, for almost the same reason why you cannot do `new T()`. Each array in Java, by design, stores the component type (i.e. `T.class`) inside it; therefore you need the class of T at runtime to create such an array. – newacct May 29 '10 at 23:56
  • 2
    You still can use `new Box>[n]`, which might be sometimes sufficient, although it wouldn't help in your example. – Bartosz Klimek Jul 02 '12 at 07:58
  • 1
    @BartKiers I don't get it... this still does not compile (java-8) : `Box[] bsa = new Box[3];` did anything change in java-8 and up I assume? – Eugene Mar 12 '18 at 12:32
  • 1
    @Eugene, Arrays of specific generic types simply aren't allowed becuase they can lead to a loss of type safety as demonstrated in the sample. It is not allowed in any version of Java. The answer starts as "Arrays of generic types are not allowed because they're not sound. " – garnet Jan 01 '19 at 13:56
  • @BartKiers - Can we do this instead "T[ ] elements = new T[num]" ? – MasterJoe Apr 05 '20 at 23:52
52

By failing to provide a decent solution, you just end up with something worse IMHO.

The common work around is as follows.

T[] ts = new T[n];

is replaced with (assuming T extends Object and not another class)

T[] ts = (T[]) new Object[n];

I prefer the first example, however more academic types seem to prefer the second, or just prefer not to think about it.

Most of the examples of why you can't just use an Object[] equally apply to List or Collection (which are supported), so I see them as very poor arguments.

Note: this is one of the reasons the Collections library itself doesn't compile without warnings. If you this use-case cannot be supported without warnings, something is fundamentally broken with the generics model IMHO.

Hearen
  • 6,019
  • 2
  • 36
  • 50
Peter Lawrey
  • 498,481
  • 72
  • 700
  • 1,075
  • 6
    You have to be careful with the second one. If you return the array created in such a way to someone who expects, say, a `String[]` (or if you store it in a field that is publicly accessible of type `T[]`, and someone retrieves it), then they will get a ClassCastException. – newacct May 30 '10 at 00:01
  • 5
    I voted this answer down because your preferred example is not permitted in Java and your second example may throw a ClassCastException – José Roberto Araújo Júnior Jan 31 '14 at 02:27
  • 5
    @JoséRobertoAraújoJúnior It is quite clear the first example needs to be replaced with the second example. It would be more helpful for you to explain why the second example can throw a ClassCastException as it wouldn't be obvious to everyone. – Peter Lawrey Feb 01 '14 at 08:48
  • 3
    @PeterLawrey I created a self-answered question showing why `T[] ts = (T[]) new Object[n];` is a bad idea: http://stackoverflow.com/questions/21577493/why-not-create-an-object-and-cast-to-a-generic-type-whats-the-solution – José Roberto Araújo Júnior Feb 05 '14 at 12:40
  • @MarkoTopolnik I downvoted him because 1) The OP asked why he can't do that in java and not how he could do, so he didn't answered the question. 2) He said his answer has 2 example because he prefer the first example but has actually only one. 3) He's only example doesn't create a T[] but creates an Object[] that can cause issues. My self-answered question is not related to this question but is related to the question Peter did, he asked me to explain why he's example can throw an exception because it was not clear, so I explained in a different question – José Roberto Araújo Júnior Feb 05 '14 at 12:57
  • @MarkoTopolnik The OP is not asking opinions, he's asking explanation why he can't do `new T[initialCapacity]` when `T` is a generic class, he's asking this because he don't understand why java disallows it. Also, _alternative disign choice which someone would have liked better_ would be a chatty topic and would be against stackoverflow rules [You should only ask practical, answerable questions based on actual problems that you face. Chatty, open-ended questions diminish the usefulness of our site and push other questions off the front page.](http://stackoverflow.com/help/dont-ask) – José Roberto Araújo Júnior Feb 05 '14 at 13:13
  • 1
    @MarkoTopolnik I should be given a medal for answering all your comments to explain the same thing I've already said, the only thing that changed from my original reason is that I though that he said `T[] ts = new T[n];` was a valid example. I'll keep the vote because he's answer can cause issues and confusions to other devs and is also off-topic. Also, I'll stop comment about this. – José Roberto Araújo Júnior Feb 05 '14 at 13:32
48

Arrays Are Covariant

Arrays are said to be covariant which basically means that, given the subtyping rules of Java, an array of type T[] may contain elements of type T or any subtype of T. For instance

Number[] numbers = new Number[3];
numbers[0] = newInteger(10);
numbers[1] = newDouble(3.14);
numbers[2] = newByte(0);

But not only that, the subtyping rules of Java also state that an array S[] is a subtype of the array T[] if S is a subtype of T, therefore, something like this is also valid:

Integer[] myInts = {1,2,3,4};
Number[] myNumber = myInts;

Because according to the subtyping rules in Java, an array Integer[] is a subtype of an array Number[] because Integer is a subtype of Number.

But this subtyping rule can lead to an interesting question: what would happen if we try to do this?

myNumber[0] = 3.14; //attempt of heap pollution

This last line would compile just fine, but if we run this code, we would get an ArrayStoreException because we’re trying to put a double into an integer array. The fact that we are accessing the array through a Number reference is irrelevant here, what matters is that the array is an array of integers.

This means that we can fool the compiler, but we cannot fool the run-time type system. And this is so because arrays are what we call a reifiable type. This means that at run-time Java knows that this array was actually instantiated as an array of integers which simply happens to be accessed through a reference of type Number[].

So, as we can see, one thing is the actual type of the object, an another thing is the type of the reference that we use to access it, right?

The Problem with Java Generics

Now, the problem with generic types in Java is that the type information for type parameters is discarded by the compiler after the compilation of code is done; therefore this type information is not available at run time. This process is called type erasure. There are good reasons for implementing generics like this in Java, but that’s a long story, and it has to do with binary compatibility with pre-existing code.

The important point here is that since at run-time there is no type information, there is no way to ensure that we are not committing heap pollution.

Let’s consider now the following unsafe code:

List<Integer> myInts = newArrayList<Integer>();
myInts.add(1);
myInts.add(2);
List<Number> myNums = myInts; //compiler error
myNums.add(3.14); //heap polution

If the Java compiler does not stop us from doing this, the run-time type system cannot stop us either, because there is no way, at run time, to determine that this list was supposed to be a list of integers only. The Java run-time would let us put whatever we want into this list, when it should only contain integers, because when it was created, it was declared as a list of integers. That’s why the compiler rejects line number 4 because it is unsafe and if allowed could break the assumptions of the type system.

As such, the designers of Java made sure that we cannot fool the compiler. If we cannot fool the compiler (as we can do with arrays) then we cannot fool the run-time type system either.

As such, we say that generic types are non-reifiable, since at run time we cannot determine the true nature of the generic type.

I skipped some parts of this answers you can read full article here: https://dzone.com/articles/covariance-and-contravariance

Lavish Kothari
  • 1,580
  • 14
  • 23
Humoyun Ahmad
  • 6,560
  • 4
  • 41
  • 49
35

The reason this is impossible is that Java implements its Generics purely on the compiler level, and there is only one class file generated for each class. This is called Type Erasure.

At runtime, the compiled class needs to handle all of its uses with the same bytecode. So, new T[capacity] would have absolutely no idea what type needs to be instantiated.

Motes
  • 3,383
  • 1
  • 22
  • 22
Durandal
  • 19,415
  • 2
  • 32
  • 62
18

The answer was already given but if you already have an Instance of T then you can do this:

T t; //Assuming you already have this object instantiated or given by parameter.
int length;
T[] ts = (T[]) Array.newInstance(t.getClass(), length);

Hope, I could Help, Ferdi265

Ferdi265
  • 2,179
  • 15
  • 15
  • 1
    This is a nice solution. But this will get unchecked warnings (cast from Object to T[]). Another "slower" but "warning-free" solution would be: `T[] ts = t.clone(); for (int i=0; i – midnite Jul 20 '13 at 17:46
  • 1
    In addition, if what we kept is `T[] t`, then it would be `(T[]) Array.newInstance(t.getClass().getComponentType(), length);`. i did spend some times to figure out `getComponentType()`. Hope this helps others. – midnite Jul 26 '13 at 16:42
  • 1
    @midnite `t.clone()` will not return `T[]`. Because `t` is not Array in this answer. – xmen Sep 25 '14 at 02:02
6

The main reason is due to the fact that arrays in Java are covariant.

There's a good overview here.

GaryF
  • 22,828
  • 9
  • 56
  • 72
  • I don't see how you could support "new T[5]" even with invariant arrays. – Dimitris Andreou May 29 '10 at 08:19
  • 2
    @DimitrisAndreou Well, the whole thing is rather a comedy of errors in the Java design. It all started with array covariance. Then, once you have array covariance, you can cast `String[]` to `Object` and store an `Integer` in it. So then they had to add a runtime type check for array stores (`ArrayStoreException`) because the issue could not be caught at compile-time. (Otherwise, an `Integer` actually could be stuck in a `String[]`, and you would get an error when you tried to retrieve it, which would be horrible.) ... – Radon Rosborough Dec 24 '14 at 15:46
  • 2
    @DimitrisAndreou … Then, once you have put a runtime check in place of a far sounder compile-time check, you run into type erasure (also an unfortunate design flaw -- included only for backward compatibility). Type erasure means that you _can't_ do runtime type checks for generic types. So therefore, to avoid the array storage type problem, you simply can't have generic arrays. If they had simply made arrays invariant in the first place, we could just do compile-time type checks without running afoul of erasure. – Radon Rosborough Dec 24 '14 at 15:49
  • … I have just discovered the five-minute editing period for comments. `Object` should have been `Object[]` in my first comment. – Radon Rosborough Dec 24 '14 at 15:59
3

I like the answer indirectly given by Gafter. However, I propose it is wrong. I changed Gafter's code a little. It compiles and it runs for a while then it bombs where Gafter predicted it would

class Box<T> {

    final T x;

    Box(T x) {
        this.x = x;
    }
}

class Loophole {

    public static <T> T[] array(final T... values) {
        return (values);
    }

    public static void main(String[] args) {

        Box<String> a = new Box("Hello");
        Box<String> b = new Box("World");
        Box<String> c = new Box("!!!!!!!!!!!");
        Box<String>[] bsa = array(a, b, c);
        System.out.println("I created an array of generics.");

        Object[] oa = bsa;
        oa[0] = new Box<Integer>(3);
        System.out.println("error not caught by array store check");

        try {
            String s = bsa[0].x;
        } catch (ClassCastException cause) {
            System.out.println("BOOM!");
            cause.printStackTrace();
        }
    }
}

The output is

I created an array of generics.
error not caught by array store check
BOOM!
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
    at Loophole.main(Box.java:26)

So it appears to me you can create generic array types in java. Did I misunderstand the question?

Community
  • 1
  • 1
emory
  • 10,259
  • 1
  • 28
  • 55
  • Your example is different from what I've asked. What you described are the dangers of array covariance. Check it out (for .NET : http://blogs.msdn.com/b/ericlippert/archive/2007/10/17/covariance-and-contravariance-in-c-part-two-array-covariance.aspx ) – devoured elysium May 28 '10 at 11:28
  • Hopefully you get a type-safety warning from the compiler, yes? – Matt McHenry May 28 '10 at 11:34
  • 1
    Yes, I get a type-safety warning. Yes, I see that my example is not responsive to the question. – emory May 28 '10 at 11:51
  • Actually you get multiple warnings due to sloppy initialization of a,b,c. Also, this is well known and affects the core library, e.g. java.util.Arrays.asList(T...). If you pass any non-reifiable type for T, you get a warning (because the created array has a less precise type than the code pretends), and it's super ugly. It would be better if *the author* of this method got the warning, instead of emitting it at usage site, given that the method itself is safe, it doesn't expose the array to the user. – Dimitris Andreou May 29 '10 at 08:34
  • 1
    You did not create a generic array here. The compiler created a (non-generic) array for you. – newacct May 29 '10 at 23:57
2

I know I'm a little late to the party here, but I figured I might be able to help any future googlers since none of these answers fixed my issue. Ferdi265's answer helped immensely though.

I'm trying to create my own Linked list, so the following code is what worked for me:

package myList;
import java.lang.reflect.Array;

public class MyList<TYPE>  {

    private Node<TYPE> header = null;

    public void clear() {   header = null;  }

    public void add(TYPE t) {   header = new Node<TYPE>(t,header);    }

    public TYPE get(int position) {  return getNode(position).getObject();  }

    @SuppressWarnings("unchecked")
    public TYPE[] toArray() {       
        TYPE[] result = (TYPE[])Array.newInstance(header.getObject().getClass(),size());        
        for(int i=0 ; i<size() ; i++)   result[i] = get(i); 
        return result;
    }


    public int size(){
         int i = 0;   
         Node<TYPE> current = header;
         while(current != null) {   
           current = current.getNext();
           i++;
        }
        return i;
    }  

In the toArray() method lies the way to create an array of a generic type for me:

TYPE[] result = (TYPE[])Array.newInstance(header.getObject().getClass(),size());    
Derek Ziemba
  • 2,087
  • 17
  • 20
2

In my case, I simply wanted an array of stacks, something like this:

Stack<SomeType>[] stacks = new Stack<SomeType>[2];

Since this was not possible, I used the following as a workaround:

  1. Created a non-generic wrapper class around Stack (say MyStack)
  2. MyStack[] stacks = new MyStack[2] worked perfectly well

Ugly, but Java is happy.

Note: as mentioned by BrainSlugs83 in the comment to the question, it is totally possible to have arrays of generics in .NET

David Airapetyan
  • 4,312
  • 2
  • 33
  • 52
2

From Oracle tutorial:

You cannot create arrays of parameterized types. For example, the following code does not compile:

List<Integer>[] arrayOfLists = new List<Integer>[2];  // compile-time error

The following code illustrates what happens when different types are inserted into an array:

Object[] strings = new String[2];
strings[0] = "hi";   // OK
strings[1] = 100;    // An ArrayStoreException is thrown.

If you try the same thing with a generic list, there would be a problem:

Object[] stringLists = new List<String>[];  // compiler error, but pretend it's allowed
stringLists[0] = new ArrayList<String>();   // OK
stringLists[1] = new ArrayList<Integer>();  // An ArrayStoreException should be thrown,
                                            // but the runtime can't detect it.

If arrays of parameterized lists were allowed, the previous code would fail to throw the desired ArrayStoreException.

To me, it sounds very weak. I think that anybody with a sufficient understanding of generics, would be perfectly fine, and even expect, that the ArrayStoredException is not thrown in such case.

Stick Hero
  • 21
  • 1
1

It is because generics were added on to java after they made it, so its kinda clunky because the original makers of java thought that when making an array the type would be specified in the making of it. So that does not work with generics so you have to do E[] array=(E[]) new Object[15]; This compiles but it gives a warning.

Alvin
  • 11
  • 1
0

If we cannot instantiate generic arrays, why does the language have generic array types? What's the point of having a type without objects?

The only reason I can think of, is varargs - foo(T...). Otherwise they could have completely scrubbed generic array types. (Well, they didn't really have to use array for varargs, since varargs didn't exist before 1.5. That's probably another mistake.)

So it is a lie, you can instantiate generic arrays, through varargs!

Of course, the problems with generic arrays are still real, e.g.

static <T> T[] foo(T... args){
    return args;
}
static <T> T[] foo2(T a1, T a2){
    return foo(a1, a2);
}

public static void main(String[] args){
    String[] x2 = foo2("a", "b"); // heap pollution!
}

We can use this example to actually demonstrate the danger of generic array.

On the other hand, we've been using generic varargs for a decade, and the sky is not falling yet. So we can argue that the problems are being exaggerated; it is not a big deal. If explicit generic array creation is allowed, we'll have bugs here and there; but we've been used to the problems of erasure, and we can live with it.

And we can point to foo2 to refute the claim that the spec keeps us from the problems that they claim to keep us from. If Sun had more time and resources for 1.5, I believe they could have reached a more satisfying resolution.

Sufian
  • 5,997
  • 14
  • 60
  • 111
ZhongYu
  • 18,232
  • 5
  • 28
  • 55
0

As others already mentioned, you can of course create via some tricks.

But it's not recommended.

Because the type erasure and more importantly the covariance in array which just allows a subtype array can be assigned to a supertype array, which forces you to use explicit type cast when trying to get the value back causing run-time ClassCastException which is one of the main objectives that generics try to eliminate: Stronger type checks at compile time.

Object[] stringArray = { "hi", "me" };
stringArray[1] = 1;
String aString = (String) stringArray[1]; // boom! the TypeCastException

A more direct example can found in Effective Java: Item 25.


covariance: an array of type S[] is a subtype of T[] if S is a subtype of T

Hearen
  • 6,019
  • 2
  • 36
  • 50
0

If the class uses as a parameterized type, it can declare an array of type T[], but it cannot directly instantiate such an array. Instead, a common approach is to instantiate an array of type Object[], and then make a narrowing cast to type T[], as shown in the following:

  public class Portfolio<T> {
  T[] data;
 public Portfolio(int capacity) {
   data = new T[capacity];                 // illegal; compiler error
   data = (T[]) new Object[capacity];      // legal, but compiler warning
 }
 public T get(int index) { return data[index]; }
 public void set(int index, T element) { data[index] = element; }
}
DeV
  • 669
  • 8
  • 19
0

There surely must be a good way around it (maybe using reflection), because it seems to me that that's exactly what ArrayList.toArray(T[] a) does. I quote:

public <T> T[] toArray(T[] a)

Returns an array containing all of the elements in this list in the correct order; the runtime type of the returned array is that of the specified array. If the list fits in the specified array, it is returned therein. Otherwise, a new array is allocated with the runtime type of the specified array and the size of this list.

So one way around it would be to use this function i.e. create an ArrayList of the objects you want in the array, then use toArray(T[] a) to create the actual array. It wouldn't be speedy, but you didn't mention your requirements.

So does anyone know how toArray(T[] a) is implemented?

Eliran Malka
  • 14,498
  • 5
  • 72
  • 96
Adam
  • 713
  • 1
  • 7
  • 16
  • 3
    List.toArray(T[]) works because you are essentially giving it the component type T at runtime (you are giving it an instance of the desired array type, from which it can get the array class, and then, the component class T). With the actual component type at runtime, you can always create an array of that runtime type using `Array.newInstance()`. You'll find that mentioned in many question that ask how to create an array with a type unknown at compile time. But the OP was specifically asking *why* you can't use the `new T[]` syntax, which is a different question – newacct Nov 23 '11 at 22:22
-2

Try this:

List<?>[] arrayOfLists = new List<?>[4];