En Java, y a-t-il une différence entre String.valueOf(Object)
et Object.toString()
? Existe-t-il une convention de code spécifique pour ceux-ci?
null
abord.
En Java, y a-t-il une différence entre String.valueOf(Object)
et Object.toString()
? Existe-t-il une convention de code spécifique pour ceux-ci?
null
abord.
Réponses:
Selon la documentation Java , String.valueOf()
renvoie:
si l'argument est
null
, alors une chaîne égale à"null"
; sinon, la valeur deobj.toString()
est renvoyée.
Il ne devrait donc pas vraiment y avoir de différence, sauf pour un appel de méthode supplémentaire.
De plus, dans le cas de Object#toString
, si l'instance est null
, un NullPointerException
sera jeté, donc sans doute, c'est moins sûr .
public static void main(String args[]) {
String str = null;
System.out.println(String.valueOf(str)); // This will print a String equal to "null"
System.out.println(str.toString()); // This will throw a NullPointerException
}
String.valueOf(null)
, c'est un NPE. Cela ne fonctionne que pour les objets qui sont nuls.
String.valueOf(null)
résout réellement à la valueOf(char[])
surcharge. C'est parce que char[]
c'est un type plus spécifique que Object
.
Les différences entre String.valueOf (Object) et Object.toString () sont:
1) Si la chaîne est nulle,
String.valueOf(Object)
retournera null
, alors que Object::toString()
lancera une exception de pointeur nul.
public static void main(String args[]){
String str = null;
System.out.println(String.valueOf(str)); // it will print null
System.out.println(str.toString()); // it will throw NullPointerException
}
2) Signature:
La méthode valueOf () de la classe String est statique. alors que la méthode toString () de la classe String n'est pas statique.
La signature ou la syntaxe de la méthode valueOf () de la chaîne est donnée ci-dessous:
public static String valueOf(boolean b)
public static String valueOf(char c)
public static String valueOf(char[] c)
public static String valueOf(int i)
public static String valueOf(long l)
public static String valueOf(float f)
public static String valueOf(double d)
public static String valueOf(Object o)
La signature ou la syntaxe de la toString()
méthode string est donnée ci-dessous:
public String toString()
En Java, y a-t-il une différence entre String.valueOf (Object) et Object.toString ()?
Oui. (Et plus encore si vous envisagez de surcharger!)
Comme l' explique le javadoc , String.valueOf((Object) null)
sera traité comme un cas particulier par la valueOf
méthode et la valeur "null"
est retournée. En revanche, null.toString()
vous donnera juste un NPE.
Il se trouve que String.valueOf(null)
(notez la différence!) Ne donne un NPE ... malgré la javadoc. L'explication est obscure:
Il existe un certain nombre de surcharges de String.valueOf
, mais il y en a deux qui sont pertinentes ici: String.valueOf(Object)
et String.valueOf(char[])
.
Dans l'expression String.valueOf(null)
, ces deux surcharges sont applicables , car l' null
affectation est compatible avec n'importe quel type de référence.
Lorsqu'il y a au moins deux surcharges applicables , le JLS indique que la surcharge pour le type d'argument le plus spécifique est choisie.
Puisqu'il char[]
s'agit d'un sous-type de Object
, il est plus spécifique .
Par conséquent, la String.valueOf(char[])
surcharge est appelée.
String.valueOf(char[])
lève un NPE si son argument est un tableau nul. Contrairement à String.valueOf(Object)
cela, il ne s'agit pas null
d'un cas particulier.
(Vous pouvez le confirmer en utilisant javap -c
pour examiner le code d'une méthode qui a un String.valueOf(null)
appel. Observez la surcharge qui est utilisée pour l'appel.)
Un autre exemple illustre valueOf(char[])
encore plus clairement la différence de surcharge:
char[] abc = new char[]('a', 'b', 'c');
System.out.println(String.valueOf(abc)); // prints "abc"
System.out.println(abc.toString()); // prints "[C@...."
Existe-t-il une convention de code spécifique pour ceux-ci?
Non.
Utilisez celui qui convient le mieux aux exigences du contexte dans lequel vous l'utilisez. (Avez-vous besoin du formatage pour travailler null
?)
Remarque: ce n'est pas une convention de code. C'est juste une programmation de bon sens. Il est plus important que votre code soit correct que de suivre une convention stylistique ou un dogme des «meilleures pratiques».
Opinion personnelle:
Certains développeurs prennent la mauvaise habitude (IMO) de "se défendre" contre les nulls. Vous voyez donc de nombreux tests pour les valeurs nulles et le traitement des valeurs nulles comme des cas spéciaux. L'idée semble être d'empêcher les NPE de se produire.
Je pense que c'est une mauvaise idée. En particulier, je pense que c'est une mauvaise idée si ce que vous faites quand vous trouvez un null
est d'essayer de "faire du bien" ... sans tenir compte de la raison pour laquelle il y avait un null
là.
En général, il vaut mieux éviter d' null
être là en premier lieu ... à moins que le null
n'ait une signification très spécifique dans votre application ou dans la conception de votre API. Ainsi, plutôt que d'éviter le NPE avec beaucoup de codage défensif, il est préférable de laisser le NPE se produire, puis de localiser et de corriger la source de l'inattendu null
qui a déclenché le NPE.
Alors, comment cela s'applique-t-il ici?
Eh bien, si vous y réfléchissez, utiliser String.valueOf(obj)
pourrait être un moyen de "faire du bien". C'est à éviter. S'il est inattendu obj
d'être null
dans le contexte, il vaut mieux utiliser obj.toString()
.
La plupart ont déjà été mentionnés par d'autres réponses, mais je l'ajoute simplement pour être complet:
.toString()
car elles ne sont pas une implémentation de Object
-class, elles ne String.valueOf
peuvent donc être utilisées.String.valueOf
transformera un objet donné qui est null
en String "null"
, alors que .toString()
lancera un NullPointerException
.String.valueOf
par défaut quand quelque chose comme String s = "" + (...);
est utilisé. C'est pourquoi Object t = null; String s = "" + t;
aboutira à la chaîne "null"
, et non à un NPE. StringBuilder.append
, non String.valueOf
. Alors ignorez ce que j'ai dit ici.En plus de ceux-ci, voici en fait un cas d'utilisation où String.valueOf
et .toString()
ont des résultats différents:
Disons que nous avons une méthode générique comme celle-ci:
public static <T> T test(){
String str = "test";
return (T) str;
}
Et nous allons l' appeler avec un Integer
genre comme celui - ci: Main.<Integer>test()
.
Lorsque nous créons une chaîne avec String.valueOf
cela fonctionne bien:
String s1 = String.valueOf(Main.<Integer>test());
System.out.println(s1);
Cela sortira test
vers STDOUT.
Avec un .toString()
cependant, cela ne fonctionnera pas:
String s2 = (Main.<Integer>test()).toString();
System.out.println(s2);
Cela entraînera l'erreur suivante:
java.lang.ClassCastException
: la classejava.lang.String
ne peut pas être convertie en classejava.lang.Integer
Quant à savoir pourquoi, je peux me référer à cette question séparée et à ses réponses . Bref cependant:
.toString()
il va d' abord compiler et évaluer l'objet, où la distribution de T
( ce qui est String
de Integer
casting dans ce cas) entraînera la ClassCastException
.String.valueOf
il verra le générique T
comme Object
lors de la compilation et ne se souciera même pas que ce soit un fichier Integer
. Donc, il convertira un Object
vers Object
(que le compilateur ignore tout simplement). Ensuite, il utilisera String.valueOf(Object)
, résultant en un String
comme prévu. Ainsi, même si le String.valueOf(Object)
fera un .toString()
sur le paramètre en interne, nous avons déjà ignoré le cast et il est traité comme un Object
, nous avons donc évité ce ClassCastException
qui se produit avec l'utilisation de .toString()
.Je pensais juste qu'il valait la peine de mentionner cette différence supplémentaire entre String.valueOf
et .toString()
ici également.
("" + x)
compilé en String.valueOf(x)
, mais quelque chose de plus compliqué a utilisé un StringBuffer
(nous n'avions pas StringBuilder
alors).
String.valueOf(Object)
et Object.toString()
sont littéralement la même chose.
Si vous jetez un œil à l'implémentation de String.valueOf (Object) , vous verrez qu'il ne String.valueOf(Object)
s'agit en gros que d'un appel de null-safe toString()
de l'objet approprié:
Returns the string representation of the Object argument.
Parameters:
obj an Object.
Returns:
if the argument is null, then a string equal to "null";
otherwise, the value of obj.toString() is returned.
See also:
Object.toString()
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
La différence la plus importante est la façon dont ils gèrent les références de chaîne nulles.
String str = null;
System.out.println("String.valueOf gives : " + String.valueOf(str));//Prints null
System.out.println("String.toString gives : " + str.toString());//This would throw a NullPointerExeption
Il existe une autre différence majeure entre les deux méthodes lorsque l'objet que nous convertissons est un tableau.
Lorsque vous convertissez un tableau en utilisant Object.toString (), vous obtiendrez une sorte de valeur de garbage (@ suivi du hashcode du tableau).
Pour obtenir un toString () lisible par l'homme, vous devez utiliser String.valueOf (char []); Veuillez noter que cette méthode ne fonctionne que pour Array de type char. Je recommanderais d'utiliser Arrays.toString (Object []) pour convertir des tableaux en String.
La deuxième différence est que lorsque l'objet est nul, ValueOf () renvoie une chaîne "null", tandis que toString () renverra une exception de pointeur nul.
Je ne peux pas dire exactement quelle est la différence, mais il semble y avoir une différence lors du fonctionnement au niveau des octets. Dans le scénario de chiffrement suivant, Object.toString () a produit une valeur qui n'a pas pu être déchiffrée alors que String.valueOf () fonctionnait comme prévu ...
private static char[] base64Encode(byte[] bytes)
{
return Base64.encode(bytes);
}
private static String encrypt(String encrypt_this) throws GeneralSecurityException, UnsupportedEncodingException
{
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
SecretKey key = keyFactory.generateSecret(new PBEKeySpec(PASSWORD));
Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
pbeCipher.init(Cipher.ENCRYPT_MODE, key, new PBEParameterSpec(SALT, 20));
//THIS FAILED when attempting to decrypt the password
//return base64Encode(pbeCipher.doFinal(encrypt_this.getBytes("UTF-8"))).toString();
//THIS WORKED
return String.valueOf(base64Encode(pbeCipher.doFinal(encrypt_this.getBytes("UTF-8"))));
}//end of encrypt()
valueOf(char[])
plutôt que valueOf(Object)
. Le comportement de valueOf(char[])
est très différent de char[].toString()
. Mais de toute façon, cette réponse n'est pas à propos car vous appelez une surcharge différente de celle sur laquelle la question pose la question.
Le tableau ci-dessous montre l'implémentation de java.lang.String.valueOf comme décrit dans la source de jdk8u25. Donc, selon mon commentaire, il n'y a pas de différence. Il appelle "Object.toString". Pour les types primitifs, il l'enveloppe dans sa forme objet et appelle "toString" dessus.
Voir ci-dessous:
/*
* Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
public static String valueOf(char data[]) {
return new String(data);
}
public static String valueOf(char data[], int offset, int count) {
return new String(data, offset, count);
}
public static String copyValueOf(char data[], int offset, int count) {
return new String(data, offset, count);
}
public static String copyValueOf(char data[]) {
return new String(data);
}
public static String valueOf(boolean b) {
return b ? "true" : "false";
}
public static String valueOf(char c) {
char data[] = {c};
return new String(data, true);
}
public static String valueOf(int i) {
return Integer.toString(i);
}
public static String valueOf(long l) {
return Long.toString(l);
}
public static String valueOf(float f) {
return Float.toString(f);
}
public static String valueOf(double d) {
return Double.toString(d);
}
String.valueOf
est utilisé. Pour les objets qui remplacent toString, je pense que String.valueOf pourrait appeler cela à la place. Pas sûr de cette partie cependant.