Ответ 1
Вопрос в том, что я вызываю testNull() напрямую с параметром null, я вернусь обратно, но если call callTestNull() с нулем, который вызывает testNull(), он сообщает мне, что параметр не является нулевым, а пустой массив.
Да. Если вы вызываете его аргументом с типом времени String
, компилятор знает, что не может быть String[]
, поэтому он переносит его в массив строк. Итак:
String x = null;
testNull(x);
эквивалентно:
String x = null;
testNull(new String[] { x });
В этот момент параметр (ложно названный) String
будет иметь ненулевое значение - вместо этого он будет ссылаться на массив размером 1, единственным элементом которого является нулевая ссылка.
Однако, когда вы используете литерал null
непосредственно в вызове метода, который напрямую конвертируется в String[]
, поэтому никакая упаковка не выполняется.
Если вызываемый метод является методом переменной 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
, а не нулевой тип.