Reputation: 10466
I noticed that in Java Array.newInstance()
returns Object
, rather than T[]
. It is understandable as this method was introduced before Java supports generic types.
However it is a surprise that there are no equivalent generic version of this. Java 7's Arrays.copyOf
is not the same - it copies the content of the parameter, rather than creating a new dummy array (with all null objects inside).
Since implementation of this seems trivial, are there any reason not adding it into the JRE? or I just cannot find one?
UPDATE
It seems I shall provide my own "trivial" implementation to stop misunderstand of the question.
class MyArrayUtil {
//Generic version for classes
@SuppressWarnings("unchecked")
public static <T> T[] newArrayOf(T[] t, int len){
return (T[]) Array.newInstance(t.getClass().getComponentType(), len);
}
//For array of int
public static int[] newArrayOf(int[] t, int len){
return new int[len];
}
//For other primitive types...
}
I am not posting this code as an answer because it is not the answer of the question. The question is for reason and/or existing code, not how to implement.
UPDATE
I have updated the code to make it similar to Arrays.copyOf
, and the advantage is the programmer can simply change the type of the parameter to adjust the code for another type. Also I eliminated the use of Array.newInstance
for primitive types.
Upvotes: 9
Views: 6826
Reputation: 43401
Guava provides just such a function. It's not the first time Guava (or Apache Commons) provided a commonly-used helper that the JDK doesn't have, for whatever reason.
You may know this, but some background for the googler who stumbles upon this in the future: The reason the signature can't be made generic is that the method Array.newInstance
returned Object
in Java 1.4, so for backwards compatibility, the raw version of the method should also return Object
. If it had been generified as:
<T> T[] newInstance(Class<T> componentType, int length)
...then the return type would be Object[]
, not Object
. This would break backwards compatibility, which the Java designers have always tried very hard not to do.
The Arrays.copyOf
methods only came in with Java 1.6, and thus didn't have to worry about backwards compatibility.
Upvotes: 8
Reputation: 122489
The basic reason that Array.newInstance()
cannot be declared like <T> T[] newInstance(Class<T> class, int size)
is because it can be used to create arrays of primitives. So for example, if you pass in int.class
, which has type Class<Integer>
, then from the declaration you would expect it to return an Integer[]
object. However, the function actually returns an int[]
object, which is not a subtype of Integer[]
, so it has the wrong type.
Sure, they could add an additional method like newReferenceArrayInstance()
that prohibits primitive types (e.g. throws an exception when passed a primitive type) and thus can safely be declared to return T[]
. However, that seems like adding a completely redundant method solely for avoiding an unchecked cast.
Upvotes: 3
Reputation: 36679
No, you need to pass the concrete type as a parameter one way or the other. As you mentioned, Arrays.copyOf
shows this in action.
Class<T> type = determinteTheTypeSomehow();
return (T[]) Array.newInstance(type, length);
Upvotes: 4