Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is foo(1,2,3) not passed to varargs method foo(Object... ) as an Integer[]

Please regard the following lines of code:

public static void main(String[] args)  {
    foo(1,2,3);
    System.out.println("-------------------------------------");
    foo(new Integer(1), new Integer(2), new Integer(3));
    System.out.println("-------------------------------------");
    foo(new Integer[]{1,2,3});
    System.out.println("-------------------------------------");
    foo(new Integer[] {new Integer(1), new Integer(2), new Integer(3)});
}

public static void foo(Object... bar) {
    System.out.println("bar instanceof Integer[]:\t" + (bar instanceof Integer[]));
    System.out.println("bar[0] instanceof Integer:\t" + (bar[0] instanceof Integer));
    System.out.println("bar.getClass().isArray():\t" + bar.getClass().isArray());
}

The output of this code snippet is:

bar instanceof Integer[]:   false
bar[0] instanceof Integer:  true
bar.getClass().isArray():   true
-------------------------------------
bar instanceof Integer[]:   false
bar[0] instanceof Integer:  true
bar.getClass().isArray():   true
-------------------------------------
bar instanceof Integer[]:   true
bar[0] instanceof Integer:  true
bar.getClass().isArray():   true
-------------------------------------
bar instanceof Integer[]:   true
bar[0] instanceof Integer:  true
bar.getClass().isArray():   true

And this confuses me quite a bit! I don't understand why in case of foo(1,2,3) the term bar instanceof Integer[] is false.

If in these cases bar is not an instance of Integer[] what else is it an instance of?

like image 711
ParkerHalo Avatar asked Dec 03 '15 08:12

ParkerHalo


4 Answers

  • foo(1,2,3);

This one autoboxes 1, 2 and 3 to Integer(s) and since they are Object sub-types, an Object[] array is created, consisting of three Integers. An array Object[] is not Integer[] and that's why you get false.


  • foo(new Integer(1), new Integer(2), new Integer(3));

Here, no auto boxing applies, but in the end you will again have an array Object[] that consist of three Integers. Again, Object[] is not Integer[] and that's why you get false.


  • foo(new Integer[]{1,2,3});

Here you have only one argument, unlike the previous two cases, where you had three wrapped into one array. So, having only one argument Integer[], at Runtime the comparison bar instanceof Integer[] will return true, because integers is what you actually have.


  • foo(new Integer[] {new Integer(1), new Integer(2), new Integer(3)});

Same as the previous one - at Runtime you will check if the provided array Integer[] is an array of Integers, which is true.

like image 103
Konstantin Yovkov Avatar answered Oct 19 '22 00:10

Konstantin Yovkov


According to the Java Language Specification:

the result of the instanceof operator is true if the value of the RelationalExpression is not null and the reference could be cast (§15.16) to the ReferenceType without raising a ClassCastException.

In your case the Object[] parameter cannot be cast to an Integer[] so it returns false.

like image 5
Ortomala Lokni Avatar answered Oct 18 '22 23:10

Ortomala Lokni


the case where bar is not an array of integer is because it is an array of Object as you specified in your foo method signature: Object... args is syntactic sugar for Object[] args and when resolving to this method the compiler will create an array of Object.

In order to always have an array of Integer you could change your foo method signature to foo(Integer... args)

like image 3
benzonico Avatar answered Oct 19 '22 00:10

benzonico


Varargs are just syntactic sugar for creating and passing arrays. Since you defined your method as

public static void foo(Object... bar) 

Java creates an Object[] array for you if you call the method as foo(1,2,3) or foo(new Integer(1), new Integer(2), new Integer(3)).

However, you can also pass your own array to a method which requires a varargs parameter. In this case Java does not create a new array for you, it just passes the array you created. In the last two calls you explicitly create an Integer[] array.

like image 3
Hoopje Avatar answered Oct 19 '22 00:10

Hoopje