The JLS specifies this behavior (creation of an array of elements of the type that is the variable arity parameter type, i.e. if the vararg method is foo(Bar bar, Baz baz, T...)
then the array created on method invocation is of type T[]
), if you find the right spot:
From JLS 8.4.1 (Oracle site having trouble at the moment, I had to use the Internet Archive):
If the last formal parameter is a
variable arity parameter of type T, it
is considered to define a formal
parameter of type T[]. The method is
then a variable arity method.
Otherwise, it is a fixed arity method.
Invocations of a variable arity method
may contain more actual argument
expressions than formal parameters.
All the actual argument expressions
that do not correspond to the formal
parameters preceding the variable
arity parameter will be evaluated and
the results stored into an array that
will be passed to the method
invocation (§15.12.4.2).
From JLS 15.12.4.2:
15.12.4.2 Evaluate Arguments The process of evaluating of the argument
list differs, depending on whether the
method being invoked is a fixed arity
method or a variable arity method
(§8.4.1).
If the method being invoked is a
variable arity method (§8.4.1) m, it
necessarily has n>0 formal parameters.
The final formal parameter of m
necessarily has type T[] for some T,
and m is necessarily being invoked
with k >= 0 actual argument expressions.
If m is being invoked with k != n actual
argument expressions, or, if m is
being invoked with k=n actual argument
expressions and the type of the kth
argument expression is not assignment
compatible with T[], then the argument
list (e1, ... , en-1, en, ...ek) is
evaluated as if it were written as
(e1, ..., en-1, new T[]{en, ..., ek}).
The argument expressions (possibly
rewritten as described above) are now
evaluated to yield argument values.
Each argument value corresponds to
exactly one of the method's n formal
parameters.
The argument expressions, if any, are
evaluated in order, from left to
right. If the evaluation of any
argument expression completes
abruptly, then no part of any argument
expression to its right appears to
have been evaluated, and the method
invocation completes abruptly for the
same reason.The result of evaluating
the jth argument expression is the jth
argument value, for 1 <= j <= n. Evaluation
then continues, using the argument
values, as described below.
So I maintain my original answer (see below).
I believe the answer is in the declaration:
public static Object combine(Object... objs)
The compiler matches this method, and therefore for varargs it allocates an Object[]
. There is no reason for it to allocate an Integer[]
.
trial test:
package com.example.test;
public class Varargs1 {
public static void varargs(Object... objs) {
System.out.println(objs.getClass());
}
public static void main(String[] args) {
varargs("1", "2", "3");
varargs(1, 2, 3);
Integer[] ints = {1,2,3};
varargs(ints); // Eclipse yields the following warning:
/*
* The argument of type Integer[] should explicitly be
* cast to Object[] for the invocation of the varargs
* method varargs(Object...) from type Varargs1.
* It could alternatively be cast to Object for a
* varargs invocation
*/
}
}
which prints:
class [Ljava.lang.Object;
class [Ljava.lang.Object;
class [Ljava.lang.Integer;
Finally, if you want the compiler to be more specific, use generic methods:
package com.example.test;
public class Varargs2 {
public static <T> void varargs(T... objs) {
System.out.println(objs.getClass());
}
public static void main(String[] args) {
varargs("1", "2", "3");
varargs(1, 2, 3);
varargs(1, "2", 3); // warning from Eclipse:
/*
* Type safety : A generic array of
* Object&Comparable<?>&Serializable
* is created for a varargs parameter
*/
}
}
which prints:
class [Ljava.lang.String;
class [Ljava.lang.Integer;
class [Ljava.lang.Comparable;