134 votes

Pourquoi String.valueOf(null) provoque-t-il une NullPointerException ?

Selon la documentation, la méthode String.valueOf(Object obj) retours :

si l'argument est null puis une chaîne égale à "null" ; sinon, la valeur de obj.toString() est renvoyé.

Mais comment se fait-il que lorsque j'essaie de faire ça :

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

il jette NPE à la place ? (essayez vous-même si vous n'y croyez pas !)

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

Comment ça se fait que ça arrive ? La documentation me ment-elle ? S'agit-il d'un bogue majeur de Java ?

210voto

polygenelubricants Points 136838

Le problème est que String.valueOf La méthode est surchargé :

Le langage de spécification Java impose que dans ce type de cas, la surcharge la plus spécifique est choisi :

JLS 15.12.2.5 Choix de la méthode la plus spécifique

Si plusieurs méthodes membres sont à la fois accessibles et applicables à l'invocation d'une méthode, il est nécessaire d'en choisir une pour fournir le descripteur de l'envoi de la méthode d'exécution. Le langage de programmation Java utilise la règle selon laquelle la méthode le plus spécifique est choisie.

A char[] est-un Object mais pas tous Object est un char[] . Par conséquent, char[] es plus spécifique que Object et comme spécifié par le langage Java, l'élément String.valueOf(char[]) La surcharge est choisie dans ce cas.

String.valueOf(char[]) s'attend à ce que le tableau ne soit pas null et puisque null est donné dans ce cas, il lance alors NullPointerException .

La "solution" facile est de lancer le null Object comme suit :

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

Questions connexes


Morale de l'histoire

Il y en a plusieurs qui sont importants :

  • Effective Java 2e édition, point 41 : utiliser judicieusement la surcharge.
    • Ce n'est pas parce que vous pouvez surcharger, que vous devez le faire à chaque fois.
    • Elles peuvent prêter à confusion (surtout si les méthodes font des choses très différentes).
  • En utilisant un bon IDE, vous pouvez vérifier quelle surcharge est sélectionnée au moment de la compilation.
    • Avec Eclipse, vous pouvez passer la souris sur l'expression ci-dessus et voir que en effet le valueOf(char[]) la surcharge est sélectionnée !
  • Parfois, vous voulez explicitement lancer null (exemples à suivre)

Voir aussi


Sur le casting null

Il y a au moins deux situations où le casting explicite null à un type de référence spécifique est nécessaire :

  • Pour sélectionner la surcharge (comme indiqué dans l'exemple ci-dessus)
  • Pour donner null comme argument unique d'un paramètre vararg

Un exemple simple de ce dernier est le suivant :

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

Alors, nous pouvons avoir ce qui suit :

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

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

Voir aussi

Questions connexes

5 votes

Une autre suggestion : Lorsque vous surchargez une méthode et qu'un argument peut être appelé sur deux surcharges (comme par exemple null dans ce cas), assurez-vous que les deux surcharges agissent de la même manière en ce qui concerne cette valeur !

3 votes

@Joachim : Je viens de lire l'article, et j'ai été agréablement surpris de constater que ces deux méthodes étaient explicitement discutées ! Bloch est allé un peu plus loin en affirmant que puisque String.valueOf(Object) y valueOf(char[]) font des choses complètement différentes de toute façon (indépendamment de null ou pas) que peut-être ils n'auraient pas dû être des surcharges en premier lieu.

0 votes

J'ai une question... si vous avez une méthode qui renvoie un objet, alors l'instruction return null; serait exactement la même chose que return (Object) null; ?

18voto

Joachim Sauer Points 133411

Le problème est que vous appelez String.valueOf(char[]) y pas String.valueOf(Object) .

La raison en est que Java choisira toujours la version la plus spécifique d'une méthode surchargée qui fonctionne avec les paramètres fournis. null est une valeur valide pour un Object mais c'est aussi une valeur valide pour un paramètre de type char[] paramètre.

Pour que Java utilise le Object soit passer dans null via une variable ou spécifier un cast explicite vers Object :

Object o = null;
System.out.println("String.valueOf(null) = " + String.valueOf(o));
// or
System.out.println("String.valueOf(null) = " + String.valueOf((Object) null));

4voto

cbare Points 1673

Un bug, numéroté 4867608 a été déposé pour cela en 2003, et a été résolu comme "ne réparera pas" avec cette explication.

Nous ne pouvons pas changer cela pour des raisons de compatibilité. Notez que c'est la méthode statique publique String valueOf(char data[]) qui finit par être invoquée invoquée et elle ne mentionne pas le remplacement de "null" pour des arguments arguments nuls.

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

-1voto

Profiterole Points 111

Utilice String.valueOf(null: Any) en Scala, sinon String.valueOf(null: Array[Char]) est déduit. De même, en Java, vous avez besoin d'un cast explicite si vous n'êtes pas satisfait du cast implicite. Dans IntelliJ, Ctrl+B sur votre utilisation de valueOf vous amènera à la version de valueOf que vous utilisez parmi les nombreuses que vous pouvez utiliser.

-1voto

scottbot95 Points 69

Si vous consultez la javadoc de l'option String.valueOf() vous verrez qu'il est stipulé que si vous passez une valeur nulle dans la méthode, il y aura un NullPointerException . De plus, si votre IDE le permet, vous pouvez regarder le code source de ces méthodes et vous verrez qu'il y a généralement du code qui cible spécifiquement la possibilité que l'entrée soit nulle et lance un NullPointerException .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X