Em Java, existe alguma diferença entre String.valueOf(Object)
e Object.toString()
? Existe uma convenção de código específica para eles?
null
primeiro.
Em Java, existe alguma diferença entre String.valueOf(Object)
e Object.toString()
? Existe uma convenção de código específica para eles?
null
primeiro.
Respostas:
De acordo com a documentação Java , String.valueOf()
retorna:
se o argumento for
null
, uma sequência igual a"null"
; caso contrário, o valor deobj.toString()
é retornado.
Portanto, realmente não deve haver diferença, exceto por uma invocação de método adicional.
Além disso, no caso de Object#toString
, se a instância for null
, a NullPointerException
será lançada, então, sem dúvida, é 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)
, isso é um NPE. Funciona apenas para objetos que são nulos.
String.valueOf(null)
realmente resolve a valueOf(char[])
sobrecarga. Isso ocorre porque char[]
é um tipo mais específico que Object
.
As diferenças entre String.valueOf (Object) e Object.toString () são:
1) Se a string for nula,
String.valueOf(Object)
retornará null
, enquanto Object::toString()
lançará uma exceção de ponteiro 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) Assinatura:
O método valueOf () da classe String é estático. enquanto o método toString () da classe String não é estático.
A assinatura ou sintaxe do método valueOf () da string é fornecida abaixo:
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)
A assinatura ou sintaxe do toString()
método da string é fornecida abaixo:
public String toString()
Em Java, existe alguma diferença entre String.valueOf (Object) e Object.toString ()?
Sim. (E mais ainda, se você considerar sobrecarregar!)
Como o javadoc explica, String.valueOf((Object) null)
será tratado como um caso especial pelo valueOf
método e o valor "null"
será retornado. Por outro lado, null.toString()
apenas fornecerá um NPE.
Acontece que String.valueOf(null)
(note a diferença!) Faz dar um NPE ... apesar do javadoc. A explicação é obscura:
Há várias sobrecargas de String.valueOf
, mas há duas que são relevantes aqui: String.valueOf(Object)
e String.valueOf(char[])
.
Na expressão String.valueOf(null)
, essas duas sobrecargas são aplicáveis , pois null
é uma atribuição compatível com qualquer tipo de referência.
Quando há duas ou mais sobrecargas aplicáveis , o JLS diz que a sobrecarga para o tipo de argumento mais específico é escolhida.
Como char[]
é um subtipo de Object
, é mais específico .
Portanto, a String.valueOf(char[])
sobrecarga é chamada.
String.valueOf(char[])
lança um NPE se seu argumento for uma matriz nula. Ao contrário String.valueOf(Object)
, não trata null
como um caso especial.
(Você pode confirmar isso usando javap -c
para examinar o código de um método que possui uma String.valueOf(null)
chamada. Observe a sobrecarga usada na chamada.)
Outro exemplo ilustra a diferença na valueOf(char[])
sobrecarga ainda mais claramente:
char[] abc = new char[]('a', 'b', 'c');
System.out.println(String.valueOf(abc)); // prints "abc"
System.out.println(abc.toString()); // prints "[C@...."
Existe uma convenção de código específica para eles?
Não.
Use o que for mais adequado aos requisitos do contexto em que você o está usando. (Você precisa da formatação para trabalhar null
?)
Nota: isso não é uma convenção de código. É apenas programação de senso comum. É mais importante que seu código esteja correto do que seguir algumas convenções estilísticas ou dogmas de "melhores práticas".
Opinião pessoal:
Alguns desenvolvedores adquirem o mau hábito (IMO) de "defender" contra nulos. Então você vê muitos testes para nulos e trata os nulos como casos especiais. A idéia parece impedir que o NPE aconteça.
Acho que é uma má idéia. Em particular, acho que é uma má idéia se o que você faz quando encontra um null
é tentar "fazer o bem" ... sem considerar o porquê de haver um null
lá.
Em geral, é melhor evitar null
estar lá em primeiro lugar ... a menos que isso null
tenha um significado muito específico no seu aplicativo ou no design da API. Portanto, em vez de evitar o NPE com muita codificação defensiva, é melhor deixar o NPE acontecer e, em seguida, rastrear e corrigir a fonte do inesperado null
que acionou o NPE.
Então, como isso se aplica aqui?
Bem, se você pensar bem, usar String.valueOf(obj)
pode ser uma maneira de "melhorar". Isso deve ser evitado. Se for inesperado obj
estar null
no contexto, é melhor usar obj.toString()
.
A maioria já foi mencionada por outras respostas, mas apenas a adiciono para completar:
.toString()
pois não são uma implementação da Object
classe-, portanto, apenasString.valueOf
podem ser usadas.String.valueOf
transformará um determinado objeto que é null
a String "null"
, enquanto .toString()
lançará umNullPointerException
.String.valueOf
por padrão quando algo como String s = "" + (...);
for usado. É por isso Object t = null; String s = "" + t;
que resultará na String "null"
, e não em um NPE. StringBuilder.append
, nãoString.valueOf
. Então ignore o que eu disse aqui.Além desses, aqui está realmente um caso de uso em que String.valueOf
e.toString()
obtém resultados diferentes:
Digamos que temos um método genérico como este:
public static <T> T test(){
String str = "test";
return (T) str;
}
E nós vamos chamá-lo com um Integer
tipo como este:Main.<Integer>test()
.
Quando criamos uma String, String.valueOf
ela funciona bem:
String s1 = String.valueOf(Main.<Integer>test());
System.out.println(s1);
Isso resultará test
em STDOUT.
No .toString()
entanto, com um não funcionará:
String s2 = (Main.<Integer>test()).toString();
System.out.println(s2);
Isso resultará no seguinte erro:
java.lang.ClassCastException
: classejava.lang.String
não pode ser convertida em classejava.lang.Integer
Quanto ao porquê, posso me referir a essa pergunta separada e suas respostas . Em suma, no entanto:
.toString()
-lo em primeiro lugar reunir e avaliar o objecto, em que o fundido a T
(que é uma String
de Integer
fundido neste caso) irá resultar naClassCastException
.String.valueOf
lo, ele verá o genérico T
como Object
durante a compilação e nem se importa com isso Integer
. Portanto, ele converterá um Object
para Object
(que o compilador simplesmente ignora). Em seguida, ele será usado String.valueOf(Object)
, resultando em um String
como esperado. Assim, mesmo que o String.valueOf(Object)
vai fazer um .toString()
sobre o parâmetro internamente, nós já pulou o elenco e sua tratado como um Object
, então temos evitado o ClassCastException
que ocorre com o uso de .toString()
.Apenas pensei que valia a pena mencionar essa diferença adicional entre String.valueOf
e .toString()
aqui também.
("" + x)
compilado String.valueOf(x)
, mas qualquer coisa mais complicada usou um StringBuffer
(não tínhamos StringBuilder
então).
String.valueOf(Object)
e Object.toString()
são literalmente a mesma coisa.
Se você der uma olhada na implementação de String.valueOf (Object) , verá que String.valueOf(Object)
é basicamente apenas uma invocação com segurança nula detoString()
do objeto apropriado:
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();
}
A diferença mais importante é a maneira como eles lidam com referências nulas de String.
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
Há mais uma grande diferença entre os dois métodos: quando o objeto que estamos convertendo é uma matriz.
Ao converter uma matriz usando Object.toString (), você obtém algum tipo de valor de lixo (@ seguido pelo código de hash da matriz).
Para obter um toString () legível por humanos, você deve usar String.valueOf (char []); Por favor note que este método funciona apenas para Array do tipo char. Eu recomendaria usar Arrays.toString (Object []) para converter matrizes em String.
A segunda diferença é quando o objeto é nulo, ValueOf () retorna uma String "null", enquanto toString () retorna uma exceção de ponteiro nulo.
Não sei dizer exatamente qual é a diferença, mas parece haver uma diferença ao operar no nível de bytes. No cenário de criptografia a seguir, Object.toString () produziu um valor que não pôde ser descriptografado, enquanto String.valueOf () funcionou conforme o esperado ...
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[])
vez de valueOf(Object)
. O comportamento de valueOf(char[])
é significativamente diferente de char[].toString()
. De qualquer forma, essa resposta não é adequada, porque você está chamando uma sobrecarga diferente daquela sobre a qual a pergunta é feita.
A seguir, mostra a implementação do java.lang.String.valueOf, conforme descrito na fonte do jdk8u25. Então, de acordo com o meu comentário, não há diferença. Ele chama "Object.toString". Para tipos primitivos, ele o agrupa em sua forma de objeto e chama "toString" nele.
Ver abaixo:
/*
* 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
é usado. Para objetos que substituem toString, acho que String.valueOf pode chamar isso. Não tenho certeza sobre essa parte embora.