En Java, ¿hay alguna diferencia entre String.valueOf(Object)
y Object.toString()
? ¿Existe una convención de código específica para estos?
null
primero.
En Java, ¿hay alguna diferencia entre String.valueOf(Object)
y Object.toString()
? ¿Existe una convención de código específica para estos?
null
primero.
Respuestas:
De acuerdo con la documentación de Java , String.valueOf()
devuelve:
si el argumento es
null
, entonces una cadena igual a"null"
; de lo contrario,obj.toString()
se devuelve el valor de .
Por lo tanto, no debería haber una diferencia, excepto una invocación de método adicional.
Además, en el caso de Object#toString
, si la instancia es null
, se NullPointerException
lanzará un , por lo que podría decirse que es menos seguro .
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)
, eso es un NPE. Solo funciona para objetos que son nulos.
String.valueOf(null)
realmente resuelve la valueOf(char[])
sobrecarga. Esto se debe a que char[]
es un tipo más específico que Object
.
Las diferencias entre String.valueOf (Object) y Object.toString () son:
1) Si la cadena es nula,
String.valueOf(Object)
regresará null
, mientras Object::toString()
que lanzará una excepción de puntero nulo.
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:
El método valueOf () de la clase String es estático. mientras que el método toString () de la clase String no es estático.
La firma o sintaxis del método valueOf () de la cadena se proporciona a continuación:
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 sintaxis del toString()
método de cadena se da a continuación:
public String toString()
En Java, ¿hay alguna diferencia entre String.valueOf (Object) y Object.toString ()?
Si. (¡Y más si consideras sobrecargar!)
Como explica el javadoc , String.valueOf((Object) null)
se tratará como un caso especial por el valueOf
método y "null"
se devolverá el valor . Por el contrario, null.toString()
solo le dará un NPE.
Resulta que String.valueOf(null)
(tenga en cuenta la diferencia!) Hace dar una NPE ... a pesar de la javadoc. La explicación es oscura:
Hay varias sobrecargas de String.valueOf
, pero hay dos que son relevantes aquí: String.valueOf(Object)
y String.valueOf(char[])
.
En la expresión String.valueOf(null)
, ambas sobrecargas son aplicables , ya null
que la asignación es compatible con cualquier tipo de referencia.
Cuando hay dos o más sobrecargas aplicables , el JLS dice que se elige la sobrecarga para el tipo de argumento más específico .
Como char[]
es un subtipo de Object
, es más específico .
Por lo tanto, String.valueOf(char[])
se llama la sobrecarga.
String.valueOf(char[])
lanza un NPE si su argumento es una matriz nula. A diferencia String.valueOf(Object)
, no se trata null
como un caso especial.
(Puede confirmar esto usando javap -c
para examinar el código de un método que tiene una String.valueOf(null)
llamada. Observe la sobrecarga que se usa para la llamada).
Otro ejemplo ilustra la diferencia en la valueOf(char[])
sobrecarga aún más claramente:
char[] abc = new char[]('a', 'b', 'c');
System.out.println(String.valueOf(abc)); // prints "abc"
System.out.println(abc.toString()); // prints "[C@...."
¿Existe una convención de código específica para estos?
No.
Utilice el que sea más apropiado para los requisitos del contexto en el que lo está utilizando. (¿ Necesita el formato para trabajar null
?)
Nota: eso no es una convención de código. Es solo programación de sentido común. Es más importante que su código sea correcto que seguir alguna convención estilística o dogma de "mejores prácticas".
Opinión personal:
Algunos desarrolladores adquieren el mal hábito (IMO) de "defenderse" de los nulos. Entonces ve muchas pruebas de nulos y trata los nulos como casos especiales. La idea parece ser evitar que suceda NPE.
Creo que esta es una mala idea. En particular, creo que es una mala idea si lo que haces cuando encuentras un null
es tratar de "hacer el bien" ... sin tener en cuenta por qué había un null
allí.
En general, es mejor evitar null
estar allí en primer lugar ... a menos que null
tenga un significado muy específico en su aplicación o diseño de API. Entonces, en lugar de evitar el NPE con mucha codificación defensiva, es mejor dejar que ocurra el NPE, y luego rastrear y corregir la fuente de lo inesperado null
que desencadenó el NPE.
Entonces, ¿cómo se aplica esto aquí?
Bueno, si lo piensas bien, usar String.valueOf(obj)
podría ser una forma de "hacer el bien". Eso debe ser evitado. Si es inesperado obj
estar null
en el contexto, es mejor usarlo obj.toString()
.
La mayoría ya ha sido mencionada por otras respuestas, pero solo la agrego para completar:
.toString()
ya que no son una implementación de la Object
clase, por lo que solo String.valueOf
se pueden usar.String.valueOf
transformará un objeto dado que está null
en la cadena "null"
, mientras .toString()
que arrojará un NullPointerException
.String.valueOf
por defecto cuando se use algo así String s = "" + (...);
. Es por eso Object t = null; String s = "" + t;
que resultará en la Cadena "null"
, y no en un NPE. StringBuilder.append
, no String.valueOf
. Ignora lo que dije aquí.Además de esos, aquí hay un caso de uso donde String.valueOf
y .toString()
tienen diferentes resultados:
Digamos que tenemos un método genérico como este:
public static <T> T test(){
String str = "test";
return (T) str;
}
Y lo vamos a llamar con un Integer
tipo como este: Main.<Integer>test()
.
Cuando creamos una cadena con String.valueOf
ella funciona bien:
String s1 = String.valueOf(Main.<Integer>test());
System.out.println(s1);
Esto dará salida test
a STDOUT.
Sin .toString()
embargo, no funcionará:
String s2 = (Main.<Integer>test()).toString();
System.out.println(s2);
Esto dará como resultado el siguiente error:
java.lang.ClassCastException
: la clasejava.lang.String
no se puede enviar a clasejava.lang.Integer
En cuanto a por qué, puedo referirme a esta pregunta separada y sus respuestas . En resumen, sin embargo:
.toString()
por primera vez compilará y evaluar el objeto, donde el elenco a T
(que es una String
de Integer
fundido en este caso) dará lugar a la ClassCastException
.String.valueOf
verá el genérico T
como Object
durante la compilación y ni siquiera le importa que sea un Integer
. Entonces lanzará un Object
to Object
(que el compilador simplemente ignora). Luego lo usará String.valueOf(Object)
, dando String
como resultado lo esperado. Entonces, a pesar de String.valueOf(Object)
que hará un .toString()
parámetro interno, ya hemos omitido el reparto y se lo trata como un Object
, así que hemos evitado lo ClassCastException
que ocurre con el uso de .toString()
.Solo pensé que valía la pena mencionar esta diferencia adicional entre String.valueOf
y .toString()
aquí también.
("" + x)
compilado String.valueOf(x)
, pero cualquier cosa más complicada usaba un StringBuffer
(no teníamos StringBuilder
entonces).
String.valueOf(Object)
y Object.toString()
son literalmente lo mismo.
Si echa un vistazo a la implementación de String.valueOf (Object) , verá que String.valueOf(Object)
es básicamente una invocación nula-segura del toString()
objeto apropiado:
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 diferencia más importante es la forma en que manejan las referencias de cadena nulas.
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
Hay una diferencia importante más entre los dos métodos es cuando el objeto que estamos convirtiendo es una matriz.
Cuando convierte una matriz usando Object.toString () obtendrá algún tipo de valor basura (@ seguido del código hash de la matriz).
Para obtener un toString () legible para humanos, debe usar String.valueOf (char []); tenga en cuenta que este método solo funciona para Array de tipo char. Recomendaría usar Arrays.toString (Object []) para convertir matrices a String.
La segunda diferencia es cuando el objeto es nulo, ValueOf () devuelve un String "nulo", mientras que toString () devolverá una excepción de puntero nulo.
No puedo decir exactamente cuál es la diferencia, pero parece haber una diferencia cuando se opera a nivel de byte. En el siguiente escenario de cifrado, Object.toString () produjo un valor que no se pudo descifrar, mientras que String.valueOf () funcionó según lo 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[])
lugar de valueOf(Object)
. El comportamiento de valueOf(char[])
es significativamente diferente a char[].toString()
. Pero de cualquier manera, esta respuesta no es apropiada porque está llamando a una sobrecarga diferente a la pregunta sobre la que pregunta.
A continuación se muestra la implementación de java.lang.String.valueOf como se describe en la fuente de jdk8u25. Entonces, según mi comentario, no hay diferencia. Se llama "Object.toString". Para los tipos primitivos, lo envuelve en su forma de objeto y lo llama "toString".
Vea abajo:
/*
* 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
se usa. Para los objetos que anulan aString, creo que String.valueOf podría llamar a eso en su lugar. Aunque no estoy seguro de esa parte.