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

Char и разность между массивами int

Когда я пытаюсь напечатать неинициализированный массив static char, он дает ошибку времени выполнения (исключение Null pointer), тогда как неинициализированный массив static int дает значение null. Почему?

public class abc {
    static int arr[];
    static char ch[];

    public static void main(String[] args) {
        System.out.println(ch); //it gives null pointer exception at run time
        System.out.println(arr); //it gives output as "null".
        }
    }
4b9b3361

Ответ 1

System.out - это экземпляр PrintStream, и этот класс имеет несколько перегруженных методов println. В вашем случае:

  • System.out.println(ch); использует public void println(char x[])
  • System.out.println(arr); использует public void println(Object x) (нет метода public void println(int[] x), поэтому ближайший доступный тип для int[], который может использовать println, - Object).

Второй метод использует

String.valueOf(x);

чтобы получить строковое представление объекта, который мы хотим распечатать, и код метода valueOf выглядит как

public static String valueOf(Object obj) {
    return (obj == null) ? "null" : obj.toString();
}

чтобы он был нулевым (вернет строку "null", если ссылка содержит null).

Первый метод находится на некотором уровне, используя

public void write(char cbuf[]) throws IOException {
    write(cbuf, 0, cbuf.length);
                 //    ^^^^^^^ this throws NPE
}

и потому что cbuf есть null cbuf.length будет вызывать исключение NullPointerException, потому что null не имеет поля length (или любого другого).

Ответ 2

Ответ существует в исходном коде PrintWriter (из которого System.out является экземпляром).

Начните с того, что неинициализированные массивы в качестве ссылочных переменных заданы по умолчанию null.

println(char[]) (в конечном итоге) пытается вызвать .length в переданном массиве. Он равен нулю, в результате получится NullPointerException. println(char[]) (в конечном итоге) вызывает write(char[]):

public void write(char buf[]) {
    write(buf, 0, buf.length);
}

Нет перегрузки println соответствия int[], но существует println(Object). Там он (в конце концов) пытается String.valueOf, передавая ссылку null, поэтому String.valueOf принимает null и возвращает String "null". println(Object) вызывает print(Object):

public void print(Object obj) {
    write(String.valueOf(obj));
}

Ответ 3

Это два разных метода, и их API полностью описывают поведение.

public void println(Object x) сначала вызывает String.valueOf, который возвращает "null", если x равно null.

См:

public void print(char[] c) вызывает метод print (char [] c), который выдает исключение NullPointerException, если c имеет значение null.

См:

Ответ 4

Фактически вы вызываете два разных перегруженных метода System.out.println(). public void println(char[] x) перегружен согласно документации. Конкретная перегрузка println(Object x) не существует для массивов int[].

Итак, когда println() вызывается в целочисленном массиве, вызывается public void println(Object x). Согласно Javadocs:

Этот метод вызывает сначала String.valueOf(x), чтобы получить распечатанную object string value, а затем ведет себя так, как будто он вызывает печать (String) а затем println().

Так как значение строки null, метод печатает null.

Метод println() работает несколько иначе, когда в качестве параметра принимает массив символов. Поверхностно, сам метод кажется похожим:

Печатает массив символов, а затем завершает линию. Этот метод ведет себя так, как будто он вызывает печать (char []), а затем println().

Однако метод print(char[]) ведет себя по-разному ключевыми способами:

Печатает массив символов. Символы преобразуются в байты в соответствии с кодировкой символов по умолчанию платформы, и эти байты записываются точно так же, как метод write (int).

Таким образом, он вызывает другой метод. В документации для print(char[]) явно указано, что в вашей ситуации вы выбрали исключение:

Throws: NullPointerException - если [входной параметр] s имеет значение null

Следовательно, причина различия в поведении.

Подробнее о методах println и print см. Javadocs: http://docs.oracle.com/javase/7/docs/api/java/io/PrintStream.html#println()