Почему String.valueOf (пустой указатель) бросает 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)

Каким образом это происходит? Документация лжет мне? Действительно ли это - главная ошибка в Java?

122
задан polygenelubricants 29 June 2010 в 11:18
поделиться

2 ответа

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

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

JLS 15. 12.2.5 Выбор наиболее специфичного метода

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

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

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

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

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

Похожие вопросы


Мораль истории

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

  • Effective Java 2nd Edition, Item 41: Use overloading judiciously
    • Только потому, что вы можете перегружать, не значит, что вы должны делать это каждый раз
    • Они могут вызвать путаницу (особенно если методы делают совершенно разные вещи)
  • Используя хорошую 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"

См. также

Похожие вопросы

196
ответ дан 24 November 2019 в 01:24
поделиться

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

Причина в том, что Java всегда выбирает наиболее конкретную версию перегруженного метода, работающего с предоставленными параметрами. null - допустимое значение для параметра Object , но также допустимое значение для параметра char [] .

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

Object o = null;
System.out.println("String.valueOf(null) = " + String.valueOf(o));
// or
System.out.println("String.valueOf(null) = " + String.valueOf((Object) null));
17
ответ дан 24 November 2019 в 01:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: