Gibt es in Java einen Unterschied zwischen String.valueOf(Object)
und Object.toString()
? Gibt es eine spezielle Code-Konvention für diese?
null
.
Gibt es in Java einen Unterschied zwischen String.valueOf(Object)
und Object.toString()
? Gibt es eine spezielle Code-Konvention für diese?
null
.
Antworten:
Nach der Java - Dokumentation , String.valueOf()
kehrt:
Wenn das Argument ist
null
, dann ist eine Zeichenfolge gleich"null"
; Andernfalls wird der Wert vonobj.toString()
zurückgegeben.
Es sollte also keinen wirklichen Unterschied geben, außer einem zusätzlichen Methodenaufruf.
Auch im Fall von Object#toString
, wenn die Instanz ist null
, wird ein NullPointerException
Wurf ausgelöst, so dass es wohl weniger sicher ist .
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)
, das ist eine NPE. Es funktioniert nur für Objekte, die null sind.
String.valueOf(null)
löst sich tatsächlich zur valueOf(char[])
Überlastung auf. Dies liegt daran, dass char[]
es sich um einen spezifischeren Typ als handelt Object
.
Unterschiede zwischen String.valueOf (Object) und Object.toString () sind:
1) Wenn der String null ist,
String.valueOf(Object)
wird zurückgegeben null
, während Object::toString()
eine Nullzeigerausnahme ausgelöst wird.
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) Unterschrift:
Die valueOf () -Methode der String-Klasse ist statisch. Die toString () -Methode der String-Klasse ist nicht statisch.
Die Signatur oder Syntax der valueOf () -Methode des Strings ist unten angegeben:
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)
Die Signatur oder Syntax der String- toString()
Methode ist unten angegeben:
public String toString()
Gibt es in Java einen Unterschied zwischen String.valueOf (Object) und Object.toString ()?
Ja. (Und mehr noch, wenn Sie eine Überlastung in Betracht ziehen!)
Wie der Javadoc erklärt, String.valueOf((Object) null)
wird er von der valueOf
Methode als Sonderfall behandelt und der Wert "null"
zurückgegeben. Im Gegensatz,null.toString()
dazu erhalten Sie nur eine NPE.
Es stellt sich heraus , dass String.valueOf(null)
(beachten Sie den Unterschied!) Hat eine NPE geben ... trotz der javadoc. Die Erklärung ist dunkel:
Es gibt eine Reihe von Überlastungen von String.valueOf
, aber es gibt zwei, die hier relevant sind: String.valueOf(Object)
und String.valueOf(char[])
.
Im Ausdruck String.valueOf(null)
sind diese beiden Überladungen anwendbar , da null
die Zuweisung mit jedem Referenztyp kompatibel ist.
Wenn zwei oder mehr zutreffen Überladungen vorliegen, gibt das JLS an, dass die Überladung für den spezifischsten Argumenttyp ausgewählt wird.
Da char[]
ist ein Subtyp vonObject
, ist er spezifischer .
Deshalb, die String.valueOf(char[])
Überlastung aufgerufen.
String.valueOf(char[])
löst eine NPE aus, wenn ihr Argument ein Null-Array ist. nicht wieString.valueOf(Object)
wird es nicht null
als Sonderfall behandelt .
(Sie können dies mit bestätigen javap -c
den Code einer Methode untersuchen, die einen String.valueOf(null)
Aufruf hat. Beobachten Sie die Überlastung, die für den Aufruf verwendet wird.)
Ein weiteres Beispiel verdeutlicht den Unterschied in der valueOf(char[])
Überlastung noch deutlicher:
char[] abc = new char[]('a', 'b', 'c');
System.out.println(String.valueOf(abc)); // prints "abc"
System.out.println(abc.toString()); // prints "[C@...."
Gibt es eine spezielle Code-Konvention für diese?
Nein.
Verwenden Sie, was für die Anforderungen des Kontexts, in dem Sie es verwenden, am besten geeignet ist. (Do Sie müssen die Formatierung Arbeit fürnull
?)
Hinweis: Dies ist keine Codekonvention. Es ist nur gesunder Menschenverstand Programmierung. Es ist wichtiger, dass Ihr Code korrekt ist, als einer Stilkonvention oder einem "Best Practice" -Dogma zu folgen.
Persönliche Meinung:
Einige Entwickler haben die schlechte Angewohnheit (IMO), sich gegen Nullen zu "verteidigen". Sie sehen also viele Tests für Nullen und behandeln Nullen als Sonderfälle. Die Idee scheint zu sein, NPE zu verhindern.
Ich denke, das ist eine schlechte Idee. Insbesondere denke ich, dass es eine schlechte Idee ist, wenn Sie null
versuchen, "gut zu machen", ohne zu überlegen, warum es dort eine null
gab.
Im Allgemeinen ist es besser, zu vermeiden, null
dass Sie überhaupt da sind ... es sei denn, das null
hat eine ganz bestimmte Bedeutung in Ihrer Anwendung oder Ihrem API-Design. Anstatt die NPE mit viel defensiver Codierung zu vermeiden, ist es besser, die NPE passieren zu lassen und dann die Quelle des Unerwarteten aufzuspüren und zu beheben null
, das die NPE ausgelöst hat.
Wie trifft dies hier zu?
Nun, wenn Sie darüber nachdenken, String.valueOf(obj)
könnte die Verwendung eine Möglichkeit sein, "Gutes zu tun". Das ist zu vermeiden. Wenn es unerwartet ist obj
, null
im Kontext zu sein, ist es besser zu verwenden obj.toString()
.
Das meiste wurde bereits in anderen Antworten erwähnt, aber ich füge es der Vollständigkeit halber hinzu:
.toString()
da sie keine Implementierung der Object
Klasse sind und daher nur String.valueOf
verwendet werden können.String.valueOf
transformiert ein bestimmtes Objekt, das sich null
in den String befindet "null"
, während .toString()
a NullPointerException
.String.valueOf
standardmäßig verwendet, wenn so etwas String s = "" + (...);
verwendet wird. Aus diesem Grund Object t = null; String s = "" + t;
wird der String "null"
und nicht ein NPE angezeigt. StringBuilder.append
, nicht String.valueOf
. Ignorieren Sie also, was ich hier gesagt habe.Zusätzlich zu diesen ist hier tatsächlich ein Anwendungsfall, wo String.valueOf
und.toString()
unterschiedliche Ergebnisse haben:
Nehmen wir an, wir haben eine generische Methode wie diese:
public static <T> T test(){
String str = "test";
return (T) str;
}
Und wir nennen es mit einem Integer
Typ wie diesem:Main.<Integer>test()
.
Wenn wir damit einen String erstellen String.valueOf
, funktioniert das einwandfrei:
String s1 = String.valueOf(Main.<Integer>test());
System.out.println(s1);
Dies wird ausgegeben test
an STDOUT ausgegeben.
Mit einem .toString()
wird es jedoch nicht funktionieren:
String s2 = (Main.<Integer>test()).toString();
System.out.println(s2);
Dies führt zu folgendem Fehler:
java.lang.ClassCastException
: Klassejava.lang.String
kann nicht in Klasse umgewandelt werdenjava.lang.Integer
Was den Grund betrifft, kann ich auf diese getrennte Frage und ihre Antworten verweisen . Kurz jedoch:
.toString()
wird es zuerst kompilieren und zu bewerten das Objekt, in dem die Besetzung auf T
(die eine ist String
zu Integer
Besetzung in diesem Fall) in dem Ergebnis ClassCastException
.String.valueOf
wird das Generikum T
wie Object
beim Kompilieren angezeigt und es ist nicht einmal wichtig, dass es ein Integer
. Es wird also ein Object
to umgewandelt Object
(was der Compiler einfach ignoriert). Dann wird es verwendet String.valueOf(Object)
, was zu einem String
wie erwartet führt. Obwohl der String.valueOf(Object)
Wille .toString()
intern einen Parameter ausführt, haben wir die Besetzung bereits übersprungen und sie wird wie eine behandelt Object
, sodass wir das vermieden haben ClassCastException
, was bei der Verwendung von auftritt .toString()
.Ich dachte nur, es wäre erwähnenswert, diesen zusätzlichen Unterschied zwischen String.valueOf
und auch .toString()
hier zu erwähnen .
("" + x)
kompiliert String.valueOf(x)
, aber alles, was komplizierter ist, hat a verwendet StringBuffer
(wir hatten es StringBuilder
damals nicht).
String.valueOf(Object)
und Object.toString()
sind buchstäblich das gleiche.
Wenn Sie sich die Implementierung von String.valueOf (Object) ansehen , werden Sie feststellen , dass dies String.valueOf(Object)
im Grunde nur ein null-sicherer Aufruf des toString()
entsprechenden Objekts ist:
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();
}
Der wichtigste Unterschied ist die Art und Weise, wie sie mit Null-String-Referenzen umgehen.
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
Es gibt einen weiteren großen Unterschied zwischen den beiden Methoden, wenn das Objekt, das wir konvertieren, ein Array ist.
Wenn Sie ein Array mit Object.toString () konvertieren, erhalten Sie eine Art Müllwert (@ gefolgt vom Hashcode des Arrays).
Um ein für Menschen lesbares toString () zu erhalten, müssen Sie String.valueOf (char []) verwenden. Bitte beachten Sie, dass diese Methode nur für Arrays vom Typ char funktioniert. Ich würde empfehlen, Arrays.toString (Object []) zum Konvertieren von Arrays in String zu verwenden.
Der zweite Unterschied besteht darin, dass ValueOf (), wenn das Objekt null ist, einen String "null" zurückgibt, während toString () eine Nullzeigerausnahme zurückgibt.
Ich kann nicht genau sagen, was der Unterschied ist, aber es scheint einen Unterschied zu geben, wenn auf Byte-Ebene gearbeitet wird. Im folgenden Verschlüsselungsszenario hat Object.toString () einen Wert erzeugt, der nicht entschlüsselt werden konnte, während String.valueOf () wie beabsichtigt funktionierte ...
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[])
eher anrufen als valueOf(Object)
. Das Verhalten von unterscheidet valueOf(char[])
sich erheblich von char[].toString()
. In beiden Fällen ist diese Antwort nicht zutreffend, da Sie eine andere Überlastung als die in der Frage gestellte nennen.
Das Folgende zeigt die Implementierung für java.lang.String.valueOf, wie in der Quelle für jdk8u25 beschrieben. Nach meinem Kommentar gibt es also keinen Unterschied. Es ruft "Object.toString" auf. Bei primitiven Typen wird es in seine Objektform eingeschlossen und "toString" darauf aufgerufen.
Siehe unten:
/*
* 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
verwendet. Für Objekte, die toString überschreiben, könnte String.valueOf dies stattdessen aufrufen. Ich bin mir jedoch nicht sicher.