tags:

views:

163

answers:

2

So for starters lets say that I have a LinkedList<String>,

I can easily convert it to an array via toArray(). i.e.

LinkedList<String> strList = new LinkedList<String>();
String[] strArray = strList.toArray(new String[0]);

But Lets say I have a LinkedList<T> Then I the following code:

LinkedList<T> tList = new LinkedList<T>();
T[] strArray = tList.toArray(new T[0]);

I get the Cannot create a generic array of T error message.

How can I get around this?

Specifically in my class I have LinkedList<AbstractNode<T>> nodes, and I am trying to implement a getAll() method that returns all the nodes as an Array.
Thanks!

Note Péter Török's answer provides the correct answer to my problem, but for me simply returning an ArrayList instead of [] as Bar mentioned, ended up smoothing my code out a lot.
Note2 after looking at my code a bit more i'm not even sure if any conversion was necessary to begin with, LinkedList was fine for what I was trying to do... :-/

+4  A: 

A workaround which is used in the class library would be (using an unchecked cast)

public <T> T[] toArray(List<T> list, T[] a) {
  if (a.length < list.size()) {
    a = (T[])java.lang.reflect.Array.newInstance(
        a.getClass().getComponentType(), list.size()));
  }
  return list.toArray(a);
}

or, with a Class parameter instead of an array:

public <T> T[] toArray(List<T> list, Class<T> k) {
     return list.toArray(
          (T[])java.lang.reflect.Array.newInstance(k, list.size()));
}

From Java Generics and Collections, chapters 6.4-5.

Inability to create generic arrays is one of the most serious restrictions in Java. Because it is so annoying, it is worth reiterating the reason it occurs: generic arrays are problematic because generics are implemented via erasure, but erasure is beneficial because it eases evolution.

The best workaround is to use ArrayList or some other class from the Collections Framework in preference to an array. We discussed the tradeoffs between collection classes and arrays in Section 2.5, and we noted that in many cases collections are preferable to arrays: because they catch more errors at compile time, because they provide more operations, and because they offer more flexibility in representation. By far, the best solution to the problems offered by arrays is to "just say no": use collections in preference to arrays.

Sometimes this won't work, because you need an array for reasons of compatibility or efficiency. Examples of this occur in the Collections Framework: for compatibility, the method toArray converts a collection to an array [...]

[...] a naïve method to convert a collection to an array will not work. The first fix we might try is to add an unchecked cast, but we will see shortly that this leads to even more perplexing problems. The correct fix will require us to resort to reflection.

Péter Török
there must be a way without using reflection and what is "a" in this code block a.getClass().getComponentType()
krmby
@krmby: no, there is no such way. Generics are implemented using erasure in Java which means that the compile time type is not known, so you can only "cheat" by getting the runtime type, which means using reflection. You might pass in a `Class<T>` and use that in `newInstance()` but that would still be reflection.
Joachim Sauer
@krmby, unfortunately there is none. Please check the updated code.
Péter Török
@krmby - that's not reflection, it's invocation.
Andreas_D
Thanks, In regards the your first example, I am having problems passing in a parameter for `T[] a`, mainly as I don't know how to instantiate `a` to pass into that method, again, I am trying to convert a LinkedList<AbstractNode<T>> to an array. Though I see what you mean about having to use reflection, and will keep tinkering with it!
KennyCason
@Kenny, the second example might be more suitable in your case. But ultimately, for this to work, you need to pass the concrete array / class token from somewhere at the top, where you actually know the type, all the way down to the conversion method :-(
Péter Török
ouch. yeah I got it to work, hehe but it definitely turned into some ugly code, I may consider refactoring my design at a more fundamental level :P
KennyCason
I just wanted to say thanks again for all the help, and you did answer my question as I asked it, but Bart's solution for using `ArrayList<T>` vs `T[]` made the world of difference for simplifying my code.
KennyCason
+1  A: 

Since Java generic is really replaceing your T with type object and casting to concrete type resolved at compilation, there is possible to create List<T>, but not T[]. (First one will be list of objects, second one is unknown) Well reflection allows you to do many ugly hacks. You can use them. Personally I use them only if there is no other ways to do something. I don't like runtime errors.

But my question is: Do you REALLY needs T[], why don't you use ArrayList<T> instead?

Bart
Interesting, I will give `ArrayList<T>` a spin
KennyCason
It was as easy as `return new ArrayList<AbstractNode<T>>(nodes);` Thanks, this made my code much cleaner
KennyCason
I had to change selected answers since Peter's answer was technically correct, but thanks for the work around!
KennyCason
That's okey I'm not obsessed with this reputation thing too much.I'm glad I could help.
Bart
glad to hear that :)
KennyCason