согласно документации, методу 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?
Проблема в том, что метод String.valueOf
является перегруженным:
Java Specification Language предписывает, что в подобных случаях выбирается наиболее специфическая перегрузка:
Если более одного метода-члена доступны и применимы к вызову метода, необходимо выбрать один из них, чтобы предоставить дескриптор для диспетчеризации метода во время выполнения. В языке программирования 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"
Есть несколько важных моментов:
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
, но также допустимое значение для параметра 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));