Количество элементов в varargs - PullRequest
0 голосов
/ 01 мая 2018

Я совершенно не понимаю, как Java рассчитывает длину переменных:

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 ]

0 голосов
/ 01 мая 2018

с декларацией

static void hello(Integer... x)

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

В случае

hello(null)

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

Если вы хотите передать один null Integer, вы можете устранить неоднозначность, явно приведя его к Integer:

hello((Integer)null);

или присвойте его переменной типа Integer first:

Integer x = null;
hello(x);

Они напечатают длину 1.

0 голосов
/ 01 мая 2018

, если причина в том, что каждый массив имеет длину, если его содержимое имеет значение, помните, что каждая позиция массива является переменной того же типа, что и его контейнер, поэтому, если вы отправляете null, массив будет пустым, где вам нужно проверить с помощью если это ноль, то выведите ноль

static void hello(Integer... x){
  if(x!=null)
   System.out.println(x.length);
  else
    System.out.println('is null');
}
0 голосов
/ 01 мая 2018

Написание этого:

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, и в результате вы получите его.

0 голосов
/ 01 мая 2018

Если вы передадите целочисленный массив не 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, вы получите исключение.

...