Подтвердить что ты не робот

Почему foo (1,2,3) не передается методу varargs foo (Object...) как целое []

Пожалуйста, обратите внимание на следующие строки кода:

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());
}

Вывод этого фрагмента кода:

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

И это меня смущает совсем немного! Я не понимаю, почему в случае foo(1,2,3) термин bar instanceof Integer[] является ложным.

Если в этих случаях bar не является экземпляром Integer[], что еще является экземпляром?

4b9b3361

Ответ 1

  • foo(1,2,3);

Этот автобокс 1, 2 и 3 до Integer (s), и поскольку они являются подтипами Object, создается массив Object[], состоящий из трех Integer s, Массив Object[] не Integer[], и почему вы получаете false.


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

Здесь нет автоматического бокса, но в конце вы снова получите массив Object[], состоящий из трех Integer s. Опять же, Object[] не Integer[], и почему вы получаете false.


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

Здесь у вас есть только один аргумент, в отличие от предыдущих двух случаев, когда у вас было три обернутых в один массив. Итак, имея только один аргумент Integer[], в Runtime сравнение bar instanceof Integer[] вернет true, потому что целые числа - это то, что вы на самом деле имеете.


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

То же, что и предыдущий, - в Runtime вы проверите, предоставлен ли массив Integer[] массивом Integer s, который равен true.

Ответ 2

В соответствии с Спецификацией языка Java:

результат оператора instanceof равен true, если значение RelationalExpression не является нулевым, и ссылка может быть отлита (§15.16) в ReferenceType без повышения исключения ClassCastException.

В вашем случае параметр Object[] не может быть добавлен к Integer[], поэтому он возвращает false.

Ответ 3

случай, когда bar не является массивом целого, является потому, что он является массивом объекта, указанным в вашей подписи метода foo: Object... args является синтаксическим сахаром для Object[] args, а при разрешении этого метода компилятор создаст массив объекта.

Чтобы всегда иметь массив Integer, вы можете изменить свою подпись foo на foo(Integer... args)

Ответ 4

Varargs - это просто синтаксический сахар для создания и передачи массивов. Поскольку вы определили свой метод как

public static void foo(Object... bar) 

Java создает для вас массив Object[], если вы вызываете метод как foo(1,2,3) или foo(new Integer(1), new Integer(2), new Integer(3)).

Однако вы также можете передать свой собственный массив методу, для которого требуется параметр varargs. В этом случае Java не создает для вас новый массив, он просто передает созданный массив. В последних двух вызовах вы явно создаете массив Integer[].

Ответ 5

В случае вызова foo(1,2,3); компилятор (в этом случае javac) генерирует код foo(new Object[]{new Integer(1), new Integer(2), new Integer(3)}).

javac применяет правила для Varargs и Autoboxing. Компилятор генерирует массив Object, потому что Object... означает Object[]. Поэтому bar не является экземпляром Integer[]. Это просто синтаксический сахар.