Почему String.valueOf (null) бросает исключение NullPointerException?

согласно документации, метод String.valueOf(Object obj) возвращает:

если аргумент null, затем строка, равная "null"; в противном случае-значение obj.toString() возвращается.

но почему когда я пытаюсь сделать это:

System.out.println("String.valueOf(null) = " + String.valueOf(null));

он бросает NPE вместо этого? (попробуйте сами если не верите!)

    Exception in thread "main" java.lang.NullPointerException
    at java.lang.String.(Unknown Source)
    at java.lang.String.valueOf(Unknown Source)

почему это происходит? Документы лгут мне? Это главная ошибка в Ява?

3 ответов


проблема в том, что String.valueOf метод перегружен:

Java Specification Language мандаты, что в таких случаях, самая специфическая перегрузка - это:

JLS 15.12.2.5 выбор наиболее конкретного метода

если доступно более одного метода элемента и применимо к вызову метода, необходимо выбрать один, чтобы предоставить дескриптор для отправки метода времени выполнения. Язык программирования Java использует правило, что наиболее специфичные метод.

A char[] и Object, но не все Object is-a char[]. Следовательно,char[] is более конкретную чем Object, и, как указано в языке Java,String.valueOf(char[]) перегрузка выбирается в данном случае.

String.valueOf(char[]) ожидает, что массив будет не -null, и с null дается в этом случае, он затем бросает NullPointerException.

легко "исправить", чтобы бросить null явно Object следующим образом:

System.out.println(String.valueOf((Object) null));
// prints "null"

вопросы


мораль

есть несколько важных:

  • эффективное Java 2nd Edition, пункт 41: используйте перегрузку разумно
    • только потому, что вы можете перегрузить, не означает, что вы должны каждый раз
    • они могут вызвать путаницу (особенно если методы делают дико разные вещи)
  • используя хорошую IDE, вы можете проверить, какой перегрузка выбирается во время компиляции
    • С Eclipse вы можете навести курсор мыши на приведенное выше выражение и увидеть, что действительно на valueOf(char[]) перегрузка выбран!
  • иногда вы хотите явно бросить null (примеры для подражания)

см. также


кастинг null

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

  • для выбора перегрузки (как показано в приведенном выше примере)
  • дать null как один аргумент к параметру с vararg

простым примером последнего является следующее:

static void vararg(Object... os) {
    System.out.println(os.length);
}

тогда, мы можем иметь следующий:

vararg(null, null, null); // prints "3"
vararg(null, null);       // prints "2"
vararg(null);             // throws NullPointerException!

vararg((Object) null);    // prints "1"

см. также

вопросы


проблема в том, что ты называешь String.valueOf(char[]) и не String.valueOf(Object).

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


ошибка с номером 4867608 был подан на этот путь еще в 2003 году, который был разрешен как "не исправит" с этим объяснением.

мы не можем изменить из-за ограничений совместимости. Обратите внимание, что это метод public static String valueOf (char data []), который заканчивается вызывается, и в нем не упоминается замена "null" для аргументы null.

@###.### 2003-05-23