Количество элементов в varargs
Я совершенно сбит с толку относительно того, как Java вычисляет длину varargs:
static void hello(Integer... x){
System.out.println(x.length);
}
public static void hi(){
hello();
}
Это печатает 0.
Когда я прохожу:
static void hello(Integer... x){
System.out.println(x.length);
}
public static void hi(){
hello(null);
}
Это вызывает исключение нулевого указателя.
А также
static void hello(Integer... x){
System.out.println(x.length);
}
public static void hi(){
Integer[] xIntegers= new Integer[44];
hello(xIntegers);
}
Это печатает 44.
Может кто-нибудь, пожалуйста, помогите мне понять?
4 ответа
Написание этого:
static void hello(Integer... x){
в основном причудливый способ написать это:
static void hello(Integer[] x){
с дополнительным бонусом, который вы можете вызвать первым таким образом:
hello(Integer.valueOf(1), Integer.valueOf(2));
вместо
hello(new Integer[]{Integer.valueOf(1), Integer.valueOf(2)});
Сказав это, вы все равно можете использовать вторую форму с методом с varargs.
Вторая проблема заключается в том, что массив, даже массив примитивов, рассматривается в Java как объект. Так что если вы напишите:
hello(null);
вы вызываете hello
с параметром, который является null
массив Integer
с, а не new Integer[]{null}
,
Первый вызов передает пустой массив, поэтому длина равна 0. Аналогично, третий вызов передает массив длиной 44, и в результате вы получите его.
Если вы передаете не null
целочисленный массив к вашему hello()
метод, то, как вы уже видели, вы можете получить доступ к длине без каких-либо проблем. Поэтому вы должны проверить null
введите и сравните это с массивом нулевой длины:
static void hello(Integer... x) {
int length = x == null ? 0 : x.length;
System.out.println(length);
if (x == null) return;
// otherwise do something
}
public static void hi() {
hello(null);
}
Обратите внимание, что значения просто передаются в виде массива, и у вас будет та же проблема со следующей версией hello()
:
static void hello(Integer[] x) { }
В этом случае, если вы также пытались прочитать длину null
вход, вы бы получили исключение.
Если причина в том, что у каждого массива есть длина, если у его содержимого есть значение, помните, что каждая позиция массива является переменной того же типа, что и его контейнер, поэтому, если вы отправляете null, массив пуст, где вам нужно проверить с помощью if it нуль печать ноль
static void hello(Integer... x){
if(x!=null)
System.out.println(x.length);
else
System.out.println('is null');
}
С декларацией
static void hello(Integer... x)
Вы можете позвонить, либо пропустив ровно одну Integer[]
(который становится x
внутри метода), или прохождение ноль или более Integer
s (и компилятор создаст Integer[]
из этого, и это становится x
внутри метода).
В случае
hello(null)
это неоднозначно, пытаетесь ли вы пройти null
значение типа Integer[]
или вы пытаетесь передать один null
значение типа Integer
(оба были бы законными). По умолчанию к прежнему (null
значение типа Integer[]
), и поэтому x
внутри метода null
а не массив из одного null
элемент. Пытаясь получить доступ .length
на null
вызывает исключение.
Если вы хотите передать один null
Integer
, вы можете решить эту двусмысленность, явно приведя ее к Integer
:
hello((Integer)null);
или назначьте его переменной типа Integer
первый:
Integer x = null;
hello(x);
Они будут печатать длиной 1.