9

Suppose I have a generic class with a generic parameter T which is a Number subclass. I would like to initialize an array of T during class construction. Is it possible? If yes how? If not why?

public class AClass<T extends Number>{
 private T array[];
 private int arrayOfInt[];
 public AClass(int size){
 arrayOfInt = new int[size];
 array = ? //what should I put here?
 } 
} 
asked Aug 28, 2011 at 16:26

4 Answers 4

9

T is only know at compile time. It is not know at runtime and thus you cannot initilise the contents of the array. However you can create the array, every value will be null.

array = (T[]) new Number[size];

EDIT: The problem with creating instances of any type is you need to know what is the default value you want and which constructor you want to call. e.g. there is no new Double()

As mentioned below, double[] will be more efficient and faster than Number[] and unless you need large long values, it will be able to store every possible value.

answered Aug 28, 2011 at 16:33

11 Comments

If I do this way, after having initialized the array with Number[size], can I do array[1] = new Double()? (supposing T is Double of course).
This will give you a ClassCastException. You need to use reflection to initialize the array after being passed an object of the same type as T (not a subclass)
@Ryan Amos: not if it doesn't get passed into code outside of the class. within the class, T is erased
@0verbose you were tagged but not tagged properly. Just typing this so you're notified.
@Peter Lawrey: oh yes. I see. A moreover a "d" instead of a "b". :)
|
4

If you want to use arrays, there are two options:

  1. Peter Lawrey's answer, array = (T[]) new Number[size];. You have to make sure never to return or pass this variable to code outside of the class that expect it to be an array of a particular type, which will cause an exception.

  2. Declare array as type Number[], then just do array = new Number[size];. The downside of this is that when you get anything out of it you will need to explicitly cast to T to use it as such.

The two are the same after type erasure, and they will both cause unchecked cast warning, so it's really a matter of personal preference. The former is more convenient, while the latter is more formally correct (you are not pretending it's a type it's not).

Alternately, some people will tell you to use an ArrayList<T> instead. But internally, an ArrayList is still implemented using one of these two options.

answered Aug 28, 2011 at 20:59

2 Comments

+1 : thank you for the explanation. I'm currently planning to use Vector or ArrayList.
Just for completeness: ArrayList is (in the Sun/OpenJDK version) implemented with the second option, using Object[] data.
2

This is not possible.

Because Java generics use type erasure, the type of T isn't known at runtime, so you can't create an array of it.

answered Aug 28, 2011 at 16:29

3 Comments

is there anyway to overcome that limitation?
@0verbose Yes, reflection. You need to have an array of type T passed in to do that.
@Paulo: Yes, that's correct. Yo would be extracting the class object from the array, so you may as well just request the class object.
0

Other options than mentioned are to use toArray(T[]) or java.lang.reflect.Array:

public class AClass<T extends Number>{
 private T array[];
 public AClass(final int size, T[] a){
 array = (new ArrayList<T>() {{
 for (int i = 0; i < size; i++) {
 add(null);
 }
 }}).toArray(a);
 }
 public AClass(int size, Class<T[ ]> clazz) { 
 array = clazz.cast(java.lang.reflect.Array.newInstance(
 clazz.getComponentType( ), size)); 
 } 
 public static void main(String[] args) {
 System.out.println("toArray: "
 + new AClass<Double>(42, new Double[]{}).array.length);
 System.out.println("java.lang.reflect.Array: "
 + new AClass<Double>(42, Double[].class).array.length);
 }
} 

PS. solution using reflection is close to one suggested in Langer's Generics FAQ (Utilities.createBuffer): How do I generically create objects and arrays?

answered Aug 28, 2011 at 18:23

14 Comments

Why on earth would you do that? You could just look at ArrayList's solution and implement that.
@RyanAmos I don't follow sorry - can you elaborate?
Here's ArrayList's source code. Instead of allocating new memory and creating an unrelated object to accomplish the task, simply use the code from the object to solve your problem: docjar.com/html/api/java/util/ArrayList.java.html
gnat - Yes, I can. That's why I didn't do -1.
@gnat: Did you actually try your solution? Your code creates a length-0 array, not an array of length size.
|

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.