Количество элементов в 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 внутри метода), или прохождение ноль или более Integers (и компилятор создаст Integer[] из этого, и это становится x внутри метода).

В случае

hello(null)

это неоднозначно, пытаетесь ли вы пройти null значение типа Integer[]или вы пытаетесь передать один null значение типа Integer (оба были бы законными). По умолчанию к прежнему (null значение типа Integer[]), и поэтому x внутри метода nullа не массив из одного null элемент. Пытаясь получить доступ .length на null вызывает исключение.

Если вы хотите передать один nullInteger, вы можете решить эту двусмысленность, явно приведя ее к Integer:

hello((Integer)null);

или назначьте его переменной типа Integer первый:

Integer x = null;
hello(x);

Они будут печатать длиной 1.

Другие вопросы по тегам