Почему 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[]
, что еще является экземпляром?
Ответы
Ответ 1
Этот автобокс 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[]
. Это просто синтаксический сахар.