Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are there any generic version of Array.newInstance?

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.

like image 524
Earth Engine Avatar asked Jul 19 '13 02:07

Earth Engine


People also ask

What is the difference between an array and a generic array?

An important difference between arrays and generics is how they enforce type checking. Specifically, arrays store and check type information at runtime. Generics, however, check for type errors at compile-time and don't have type information at runtime. Java's syntax suggests we might be able to create a new generic array:

Is it possible to initialize generic arrays?

Although we can't initialize generic arrays directly, it's still possible to achieve the equivalent operation if the precise type of information is provided by the calling code. 3. Creating a Generic Array For our example, let's consider a bounded stack data structure, MyStack, where the capacity is fixed to a certain size.

What does the second parameter in array newinstance mean?

The second parameter specifies how much space to create for the array. As the result of Array#newInstance is of type Object, we need to cast it to E [] to create our generic array. We should also note the convention of naming a type parameter clazz, rather than class, which is a reserved word in Java.

How do I implement a stack with a generic array?

As we'd like the stack to work with any type, a reasonable implementation choice would be a generic array. First, we'll create a field to store the elements of our stack, which is a generic array of type E: public MyStack(Class<E> clazz, int capacity) { elements = (E []) Array.newInstance (clazz, capacity); }


3 Answers

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.

like image 155
yshavit Avatar answered Nov 15 '22 14:11

yshavit


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);
like image 27
pstanton Avatar answered Nov 15 '22 15:11

pstanton


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.

like image 32
newacct Avatar answered Nov 15 '22 14:11

newacct