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

Поведение параметра Java 3 dots (varargs) при отсутствии аргументов или null

Я пробовал это и получал странное поведение от JAVA, может кто-нибудь объяснить это мне?

boolean testNull(String... string) {
    if(string == null) {
        return true;
    } else {
        System.out.println(string.getClass());
        return false;
    }
}

boolean callTestNull(String s) {
    return testNull(s);
}

Тогда у меня есть тестовый пример:

    @Test
    public void test_cases() {
        assertTrue(instance.testNull(null)); // NULL
        assertFalse(instance.testNull()); // NOT NULL
        assertFalse(instance.callTestNull(null)); // NOT NULL
    }
Вопрос: если я вызываю testNull() напрямую с параметром null, я получу true назад, но если вызов callTestNull() с null, который вызывает testNull(), он сообщает мне, что параметр а не пустой, но пустой массив.
4b9b3361

Ответ 1

Вопрос в том, что я вызываю testNull() напрямую с параметром null, я вернусь обратно, но если call callTestNull() с нулем, который вызывает testNull(), он сообщает мне, что параметр не является нулевым, а пустой массив.

Да. Если вы вызываете его аргументом с типом времени String, компилятор знает, что не может быть String[], поэтому он переносит его в массив строк. Итак:

String x = null;
testNull(x);

эквивалентно:

String x = null;
testNull(new String[] { x });

В этот момент параметр (ложно названный) String будет иметь ненулевое значение - вместо этого он будет ссылаться на массив размером 1, единственным элементом которого является нулевая ссылка.

Однако, когда вы используете литерал null непосредственно в вызове метода, который напрямую конвертируется в String[], поэтому никакая упаковка не выполняется.

Из JLS раздел 15.12.4.2:

Если вызываемый метод является методом переменной arity m, он обязательно имеет n > 0 формальных параметров. Окончательный формальный параметр m обязательно имеет тип T [] для некоторого T, а m обязательно вызывается с k ≥ 0 фактическими выражениями аргументов.

Если m вызывается с помощью k ≠ n фактических выражений аргумента или, если m вызывается с k = n фактическими аргументами выражения , а тип выражения k'th аргумента не является присвоением, совместимым с T [ ], то список аргументов (e1,..., en-1, en,..., ek) оценивается так, как если бы он был написан как (e1,..., en-1, new | T [] | {en,..., ek}), где | T [] | обозначает стирание (§4.6) из T [].

(Подчеркните мой.)

Бит, который я подчеркнул, - это то, почему обертка происходит только тогда, когда тип времени компиляции String, а не нулевой тип.