In Java, c'è qualche differenza tra String.valueOf(Object)
e Object.toString()
? Esiste una convenzione di codice specifica per questi?
null
primo.
In Java, c'è qualche differenza tra String.valueOf(Object)
e Object.toString()
? Esiste una convenzione di codice specifica per questi?
null
primo.
Risposte:
Secondo la documentazione Java , String.valueOf()
restituisce:
se l'argomento è
null
, allora una stringa uguale a"null"
; in caso contrario,obj.toString()
viene restituito il valore di .
Quindi non dovrebbe esserci davvero alcuna differenza se non per un'ulteriore chiamata al metodo.
Inoltre, nel caso di Object#toString
, se l'istanza lo è null
, NullPointerException
verrà generata una volontà, quindi probabilmente è meno sicura .
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)
, questo è un NPE. Funziona solo con oggetti nulli.
String.valueOf(null)
risolve effettivamente al valueOf(char[])
sovraccarico. Questo perché char[]
è un tipo più specifico di Object
.
Le differenze tra String.valueOf (Object) e Object.toString () sono:
1) Se la stringa è nulla,
String.valueOf(Object)
verrà restituito null
, mentre Object::toString()
verrà generata un'eccezione puntatore null.
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) Firma:
Il metodo valueOf () della classe String è statico. mentre il metodo toString () della classe String non è statico.
La firma o la sintassi del metodo valueOf () della stringa è riportata di seguito:
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 firma o la sintassi del toString()
metodo della stringa è riportata di seguito:
public String toString()
In Java, c'è qualche differenza tra String.valueOf (Object) e Object.toString ()?
Sì. (E ancora di più se consideri il sovraccarico!)
Come spiega javadoc , String.valueOf((Object) null)
verrà trattato come un caso speciale dal valueOf
metodo e il valore "null"
verrà restituito. Al contrario, null.toString()
ti darà solo un NPE.
Si scopre che String.valueOf(null)
(si noti la differenza!) Fa dare una NPE ... nonostante il javadoc. La spiegazione è oscura:
Ci sono una serie di sovraccarichi di String.valueOf
, ma ce ne sono due che sono rilevanti qui: String.valueOf(Object)
e String.valueOf(char[])
.
Nell'espressione String.valueOf(null)
sono applicabili entrambi questi sovraccarichi , poiché l' null
assegnazione è compatibile con qualsiasi tipo di riferimento.
Quando ci sono due o più sovraccarichi applicabili , JLS afferma che viene scelto il sovraccarico per il tipo di argomento più specifico .
Poiché char[]
è un sottotipo di Object
, è più specifico .
Pertanto String.valueOf(char[])
viene chiamato il sovraccarico.
String.valueOf(char[])
genera un NPE se il suo argomento è un array null. Diversamente String.valueOf(Object)
, non tratta null
un caso speciale.
(È possibile confermare ciò utilizzando javap -c
per esaminare il codice di un metodo che ha una String.valueOf(null)
chiamata. Osservare il sovraccarico utilizzato per la chiamata.)
Un altro esempio illustra la differenza nel valueOf(char[])
sovraccarico ancora più chiaramente:
char[] abc = new char[]('a', 'b', 'c');
System.out.println(String.valueOf(abc)); // prints "abc"
System.out.println(abc.toString()); // prints "[C@...."
Esiste una convenzione di codice specifica per questi?
No.
Utilizzare ciò che è sempre più appropriato ai requisiti del contesto in cui lo si sta utilizzando. (Hai bisogno della formattazione per cui lavorarenull
?)
Nota: questa non è una convenzione di codice. È solo una programmazione di buon senso. È più importante che il codice sia corretto piuttosto che seguire una convenzione stilistica o un dogma di "best practice".
Opinione personale:
Alcuni sviluppatori acquisiscono la cattiva abitudine (IMO) di "difendere" dai null. Quindi vedete molti test per i null e trattiamo i null come casi speciali. L'idea sembra impedire che accada l'NPE.
Penso che questa sia una cattiva idea. In particolare, penso che sia una cattiva idea se quello che fai quando trovi un null
è cercare di "fare del bene" ... senza considerare il motivo per cui c'era un null
lì.
In generale, è meglio evitare di null
essere lì in primo luogo ... a meno che non null
abbia un significato molto specifico nella tua applicazione o progettazione API. Quindi, piuttosto che evitare l'NPE con molta codifica difensiva, è meglio lasciare che l'NPE accada, quindi rintracciare e riparare l'origine dell'imprevisto null
che ha innescato l'NPE.
Quindi, come si applica qui?
Bene, se ci pensate, usare String.valueOf(obj)
potrebbe essere un modo per "fare del bene". Questo è da evitare. Se è inaspettato obj
essere null
nel contesto, è meglio usarlo obj.toString()
.
La maggior parte è già stata menzionata da altre risposte, ma la aggiungo per completezza:
.toString()
dato che non sono un'implementazione della Object
classe, quindi soloString.valueOf
possono essere utilizzati solo.String.valueOf
trasformerà un determinato oggetto che è null
nella stringa "null"
, mentre .toString()
lancerà aNullPointerException
.String.valueOf
per impostazione predefinita quando String s = "" + (...);
viene utilizzato qualcosa di simile . Questo è il motivo Object t = null; String s = "" + t;
per cui risulterà nella stringa "null"
e non in un NPE. StringBuilder.append
, no String.valueOf
. Quindi ignora quello che ho detto qui.Oltre a questi, qui è in realtà un caso d'uso in cui String.valueOf
e .toString()
hanno risultati diversi:
Diciamo che abbiamo un metodo generico come questo:
public static <T> T test(){
String str = "test";
return (T) str;
}
E che chiameremo con un Integer
tipo come questo: Main.<Integer>test()
.
Quando creiamo una stringa con String.valueOf
essa funziona benissimo:
String s1 = String.valueOf(Main.<Integer>test());
System.out.println(s1);
Questo verrà emesso test
su STDOUT.
Con un .toString()
tuttavia, non funzionerà:
String s2 = (Main.<Integer>test()).toString();
System.out.println(s2);
Ciò comporterà il seguente errore:
java.lang.ClassCastException
: la classejava.lang.String
non può essere trasmessa alla classejava.lang.Integer
Per quanto riguarda il motivo, posso fare riferimento a questa domanda separata e alle sue risposte . In breve però:
.toString()
esso deve prima elaborare e valutare l'oggetto, in cui il cast T
(che è un String
a Integer
getto in questo caso) comporterà il ClassCastException
.String.valueOf
vedrà il generico T
come Object
durante la compilazione e non si preoccupa nemmeno che sia un Integer
. Così sarà lanciare un Object
a Object
(che il compilatore semplicemente ignora). Quindi utilizzerà String.valueOf(Object)
, risultando String
come previsto. Quindi, anche se String.valueOf(Object)
eseguirà .toString()
internamente un parametro, abbiamo già ignorato il cast e trattato come un Object
, quindi abbiamo evitato ClassCastException
ciò che si verifica con l'uso di .toString()
.Ho pensato che valesse la pena menzionare questa ulteriore differenza tra String.valueOf
e anche .toString()
qui.
("" + x)
compilato String.valueOf(x)
, ma qualcosa di più complicato ha usato un StringBuffer
(non avevamo StringBuilder
allora).
String.valueOf(Object)
e Object.toString()
sono letteralmente la stessa cosa.
Se dai un'occhiata all'implementazione di String.valueOf (Object) , noterai che String.valueOf(Object)
è fondamentalmente solo una invocazione nulla-sicura toString()
dell'oggetto appropriato:
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 differenza più importante è il modo in cui gestiscono i riferimenti String null.
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
C'è ancora una differenza importante tra i due metodi quando l'oggetto che stiamo convertendo è un array.
Quando converti un array usando Object.toString () otterrai una sorta di valore garbage (@ seguito da hashcode dell'array).
Per ottenere un toString () leggibile dall'uomo, è necessario utilizzare String.valueOf (char []); per favore nota che questo metodo funziona solo per array di tipo char. Consiglierei di utilizzare Arrays.toString (Object []) per convertire array in String.
La seconda differenza è quando l'oggetto è null, ValueOf () restituisce una stringa "null", mentre toString () restituirà un'eccezione puntatore null.
Non posso dire esattamente quale sia la differenza, ma sembra esserci una differenza quando si opera a livello di byte. Nel seguente scenario di crittografia Object.toString () ha prodotto un valore che non è stato possibile decrittografare mentre String.valueOf () ha funzionato come previsto ...
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[])
piuttosto che valueOf(Object)
. Il comportamento di valueOf(char[])
è significativamente diverso da char[].toString()
. Ma in entrambi i casi, questa risposta non è a proposito perché stai chiamando un sovraccarico diverso da quello della domanda.
Di seguito viene mostrata l'implementazione per java.lang.String.valueOf come descritto nell'origine per jdk8u25. Quindi, secondo il mio commento, non c'è differenza. Chiama "Object.toString". Per i tipi primitivi, lo avvolge nella sua forma di oggetto e chiama "toString" su di esso.
Vedi sotto:
/*
* 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
viene utilizzato. Per gli oggetti che hanno la precedenza su String, penso che String.valueOf potrebbe chiamarlo invece. Non sono sicuro di quella parte però.