Appel explicite vs implicite de toString

J'avais l'habitude d'utiliser l'appel implicite de toString quand je voulais des informations de débogage sur un objet, car dans le cas où l'objet est null, il ne lance pas d'Exception.

Par exemple:

System.out.println("obj: "+obj);

Au Lieu de:

System.out.println("obj: "+obj.toString());

Y a-t-il une différence en dehors du cas null?
Ce dernier cas peut-il fonctionner, alors que le premier ne le fait pas?

Modifier:
Que fait-on exactement, en cas d'appel implicite?

32
demandé sur John Topley 2008-11-30 12:23:29

5 réponses

Il y a peu de différence. Utilisez celui qui est plus court et fonctionne plus souvent.

Si vous voulez avoir de la chaîne de valeur d'un objet pour d'autres raisons, et que vous voulez qu'il soit null amicales, faites ceci:

String s = String.valueOf(obj);

Edit : la question a été étendue, donc je vais étendre ma réponse.

Dans les deux cas, ils compilent quelque chose comme ceci:

System.out.println(new StringBuilder().append("obj: ").append(obj).toString());

Lorsque votre toString() est implicite, vous le verrez dans la deuxième ajout.

Si vous regardez le code source de java, vous verrez que StringBuilder.append(Object) ressemble à ceci:

public StringBuilder append(Object obj) {
    return append(String.valueOf(obj));
}

String.valueOf ressemble à ceci:

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

Maintenant, si vous toString() vous-même, vous contournez une vérification nulle et un cadre de pile et allez directement à ceci dans StringBuilder:

public StringBuilder append(String str) {
    super.append(str);
    return this;
}

Donc...des choses très similaires se produisent dans les deux cas. On fait juste un peu plus de travail.

52
répondu Dustin 2008-11-30 09:37:15

Comme d'autres l'ont dit - Utilisez la méthode "" + obj.

Selon la spécification du langage Java :

  • Si le terme est null, utilisez "null"
  • les types primitifs sont convertis en utilisant le constructeur de type boxed new Boolean(X) ou autre
  • {[3] } est invoqué (ou équivalent)
  • si le résultat de toString() est null, utiliser "null"
  • concaténer les chaînes.
3
répondu Draemon 2017-08-11 01:00:14

Aucune différence sauf, comme vous le dites, la sécurité nulle. Préférez toujours le premier au second.

1
répondu cletus 2008-11-30 09:25:53

En fait, si votre invariant dit que l'objet ne doit jamais être nul, cela n'a pas d'importance. Cela dépend donc si vous acceptez ou non obj d'être null.

1
répondu Pål GD 2008-11-30 11:04:08

Il est assez facile d'écrire un type de référence générique.

class ref
{
  static public class Reference<T>
  {
    private T value;
    public Reference(T value) { set(value); }
    public Reference() { set(null); }
    public void set (T value) { this.value = value; }
    public T get () { return this.value; }
    public String toString() { return String.valueOf(this.value); }
  }

  static void fillString (Reference<String> str)
  {
    str.set("foo");
  }

  public static void main (String[] args)
  {
    Reference<String> str = new Reference<String>("");
    fillString(str);
    System.out.println (str);
  }
}

L'exécuter donne la sortie requise:

javac ref.java && java ref
foo
0
répondu ceving 2013-07-16 13:09:19