What is this line checking? (Object)newType == (Object)Object[].class
It's checking simple equality (likely for the purpose of a micro-optimization, but more on that later).
The unusual casting is necessary because Class<Object[]>
(the type of Object[].class
) and Class<? extends T[]>
are incomparable types. Basically, for an equality comparison with ==
to compile, one of the sides has to be a subtype or supertype of the other.
I.e. we can't do:
// doesn't compile
// this expression can never evaluate to true
(new Integer(0) == new Float(0f))
The rules for generic types are a bit more complicated and there are a few cases where a comparison doesn't compile, but it may still evaluate to true.
The reason Class<Object[]>
is not a supertype of Class<? extends T[]>
, despite Object[]
being a supertype of all object array types, is that Java generics are invariant without the presence of a wildcard.
Another way to do the comparison would be:
(newType == (Class<? extends Object[]>)Object[].class)
What are the differences between (T[]) new Object[newLength]
and (T[]) Array.newInstance(newType.getComponentType(), newLength)
?
new Object[...]
creates an array the normal way, of a type that is statically known. Remember, the code has just checked that T[]
is Object[]
.
Array.newInstance(...)
uses reflection to dynamically create an array of the Class
type passed in.
Why Array.newInstance
not good enough for both cases?
An operation using reflection is generally slower than its non-reflective counterpart.
The reflection tutorial says:
Because reflection involves types that are dynamically resolved, certain Java virtual machine optimizations can not be performed. Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications.
Java SE is filled with micro-optimization like this. The writers of SE try to squeeze everything they can out of it.
But I wouldn't be worried about a performance hit in this case: newInstance
and copyOf
are HotSpot intrinsics. This means that ideally calls to these methods get replaced with machine-specific assembly. Anecdotally, I ran some tests and found the difference between new Object[...]
and Array.newInstance(...)
to be negligible. The code in the question is probably a relic, although it may still be useful on less well-equipped JVMs.
Reflection can also be disabled in certain contexts with strict security (such as an applet), but not typically for a normal desktop application.
When should I use this method?
In general, you will probably never use this overload. This overload is only useful if you want to change the type of the array.
Widening:
Object[] a = Arrays.copyOf(
new String[] { "hello", "world" }, 3, Object[].class);
a[2] = Character.valueOf('!');
System.out.println(Arrays.toString(a));
Narrowing:
String[] a = Arrays.copyOf(
new Object[] { "hello", "world" }, 2, String[].class);
System.out.println(String.join(" ", a));
It's more typical to use Arrays.copyOf(T[], int)
.