Czy w Javie jest jakaś różnica między String.valueOf(Object)i Object.toString()? Czy istnieje dla nich określona konwencja kodowa?
nullnajpierw sprawdza .
Czy w Javie jest jakaś różnica między String.valueOf(Object)i Object.toString()? Czy istnieje dla nich określona konwencja kodowa?
nullnajpierw sprawdza .
Odpowiedzi:
Według dokumentacji Java , String.valueOf()Powroty:
jeśli argumentem jest
null, to łańcuch równy"null"; w przeciwnym razie zwracanaobj.toString()jest wartość .
Więc tak naprawdę nie powinno być żadnej różnicy, z wyjątkiem dodatkowego wywołania metody.
Ponadto w przypadku Object#toString, gdy instancja jest null, NullPointerExceptionzostanie wyrzucona a, więc prawdopodobnie jest mniej bezpieczny .
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), to jest NPE. Działa tylko dla obiektów, które są zerowe.
String.valueOf(null)rzeczywistości rozwiązuje to valueOf(char[])przeciążenie. Dzieje się tak, ponieważ char[]jest to bardziej szczegółowy typ niż Object.
Różnice między String.valueOf (Object) i Object.toString () to:
1) Jeśli string jest pusty,
String.valueOf(Object) wróci null , podczas gdy Object::toString()zgłosi wyjątek wskaźnika o wartości 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) Podpis:
valueOf () klasy String jest statyczna. natomiast metoda toString () klasy String nie jest statyczna.
Podpis lub składnię metody valueOf () ciągu znaków podano poniżej:
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)
Podpis lub składnia metody string toString()jest podana poniżej:
public String toString()
Czy w Javie jest jakaś różnica między String.valueOf (Object) i Object.toString ()?
Tak. (I bardziej, jeśli weźmiesz pod uwagę przeciążenie!)
Jak wyjaśnia javadoc , metoda String.valueOf((Object) null)będzie traktowana jako specjalny przypadek valueOfi zwracana "null"będzie wartość . Natomiast null.toString()po prostu da ci NPE.
Okazuje się, że String.valueOf(null)(uwaga różnicę!) Nie dają NPE ... mimo javadoc. Prawdziwe wyjaśnienie 1 jest niejasne:
Istnieje wiele przeciążeń String.valueOf, ale są dwa, które są tutaj istotne: String.valueOf(Object)i String.valueOf(char[]).
W wyrażeniu String.valueOf(null)oba te przeciążenia mają zastosowanie , ponieważ nullprzypisanie jest zgodne z dowolnym typem odwołania.
Gdy istnieją dwa lub więcej odpowiednich przeciążeń, JLS mówi, że wybrano przeciążenie dla najbardziej określonego typu argumentu.
Ponieważ char[]jest podtypem Object, jest bardziej szczegółowy .
Dlatego String.valueOf(char[])wywoływane jest przeciążenie.
String.valueOf(char[])zgłasza NPE, jeśli jego argument jest tablicą zerową. W przeciwieństwie do String.valueOf(Object)tego nie traktuje to nulljako przypadku specjalnego.
Inny przykład valueOf(char[])jeszcze wyraźniej ilustruje różnicę w przeciążeniu:
char[] abc = new char[]('a', 'b', 'c');
System.out.println(String.valueOf(abc)); // prints "abc"
System.out.println(abc.toString()); // prints "[C@...."
Czy istnieje dla nich określona konwencja kodowa?
Nie.
Użyj tego, który kiedykolwiek jest najbardziej odpowiedni dla wymagań kontekstu, w którym go używasz. (Czy potrzebujesz formatowania do pracynull ?)
Uwaga: to nie jest konwencja kodowa. To po prostu programowanie oparte na zdrowym rozsądku. To jest ważniejsze , że kod jest poprawny , niż jest przestrzegać pewnych konwencji stylistycznej lub „najlepsze praktyki” dogma 2 .
1 - Możesz to potwierdzić, javap -csprawdzając kod metody, która ma String.valueOf(null)wywołanie. Obserwuj przeciążenie używane w wywołaniu.
2 - Przeczytaj „Brak dobrych praktyk” i przekaż to odniesienie następnej osobie, która powie Ci, że „najlepszą praktyką” jest zrobienie czegoś w dziedzinie programowania lub IT.
Niektórzy programiści nabierają (IMO) złego nawyku „obrony” przed zerami. Widzisz więc wiele testów dla wartości null i traktuje je jako przypadki specjalne. Wydaje się, że chodzi o to, aby zapobiec wystąpieniu NPE.
Myślę, że to zły pomysł. W szczególności uważam, że złym pomysłem jest, jeśli to, co robisz, gdy znajdujesz, nullto próba „naprawienia dobra” ... bez zastanowienia się, dlaczego tak się nullstało.
Ogólnie rzecz biorąc, lepiej jest unikać nullbycia tam w pierwszej kolejności ... chyba że nullma to bardzo konkretne znaczenie w twojej aplikacji lub projekcie API. Dlatego zamiast unikać NPE z dużą ilością kodowania obronnego, lepiej pozwolić, aby NPE się wydarzyło, a następnie wyśledzić i naprawić źródło nieoczekiwanegonull które wywołało NPE.
Więc jak to się ma tutaj?
Cóż, jeśli się nad tym zastanowić, używanie String.valueOf(obj) może być sposobem na „poprawę”. Tego należy unikać. Jeśli jest to nieoczekiwane, objaby znaleźć się nullw kontekście, lepiej użyć obj.toString().
Większość z nich została już wspomniana w innych odpowiedziach, ale dodam to tylko dla kompletności:
.toString()znaku, ponieważ nie są implementacją Object-class, więc String.valueOfmożna ich używać tylko.String.valueOfprzekształci dany obiekt, który jest nullna String "null", podczas gdy .toString()wyrzuci NullPointerException.String.valueOfdomyślnie, gdy String s = "" + (...);zostanie użyte coś podobnego . Dlatego też Object t = null; String s = "" + t;spowoduje powstanie ciągu "null", a nie NPE. StringBuilder.append, nie String.valueOf. Więc zignoruj to, co tutaj powiedziałem.Oprócz tych, tutaj jest faktycznie przypadek użycia, w którym String.valueOfi .toString()mają różne wyniki:
Powiedzmy, że mamy taką ogólną metodę:
public static <T> T test(){
String str = "test";
return (T) str;
}
Nazwiemy to następującym Integertypem:Main.<Integer>test() .
Kiedy tworzymy z String.valueOfnim String , działa dobrze:
String s1 = String.valueOf(Main.<Integer>test());
System.out.println(s1);
Spowoduje to wyjście testdo STDOUT.
Z .toString()jednak, że nie będzie działać:
String s2 = (Main.<Integer>test()).toString();
System.out.println(s2);
Spowoduje to następujący błąd:
java.lang.ClassCastException: klasajava.lang.Stringnie może być rzutowana na klasęjava.lang.Integer
Jeśli chodzi o dlaczego, mogę odnieść się do tego oddzielnego pytania i odpowiedzi na nie . W skrócie jednak:
.toString()będzie to pierwsza kompilacja i ocena obiektu, gdzie obsada do T(który jest Stringdo Integerobsady w tym przypadku) spowoduje ClassCastException.String.valueOfniego zobaczysz ogólny Tjak Objectpodczas kompilacji i nawet nie przejmuje się tym, że jest to plik Integer. Więc będzie to rzutować Objectna Object(co kompilator po prostu ignoruje). Wtedy użyje String.valueOf(Object), dając Stringzgodnie z oczekiwaniami. Więc nawet jeśli funkcja String.valueOf(Object)zrobi a .toString()na parametrze wewnętrznie, już pominęliśmy rzutowanie i jest traktowane jak an Object, więc uniknęliśmy tego, ClassCastExceptionco występuje przy użyciu .toString().Pomyślałem, że warto wspomnieć o tej dodatkowej różnicy między String.valueOfi .toString()tutaj.
("" + x)skompilowany do String.valueOf(x), ale cokolwiek bardziej skomplikowanego używało a StringBuffer(nie mieliśmy StringBuilderwtedy).
String.valueOf(Object)i Object.toString()są dosłownie tym samym.
Jeśli spojrzysz na implementację String.valueOf (Object) , zobaczysz, że String.valueOf(Object)jest to po prostu bezpieczne wywołanie toString()odpowiedniego obiektu z wartością null :
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();
}
Najważniejszą różnicą jest sposób, w jaki obsługują one zerowe odwołania typu 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
Jest jeszcze jedna główna różnica między tymi dwiema metodami, gdy konwertowany obiekt jest tablicą.
Kiedy konwertujesz tablicę za pomocą Object.toString (), otrzymasz jakiś rodzaj śmieci (@, po którym następuje hashcode tablicy).
Aby uzyskać czytelną dla człowieka metodę toString (), należy użyć String.valueOf (char []); plz zauważ, że ta metoda działa tylko dla Array typu char. Poleciłbym użycie Arrays.toString (Object []) do konwersji tablic na String.
Druga różnica polega na tym, że gdy obiekt ma wartość null, ValueOf () zwraca String „null”, a toString () zwróci wyjątek wskaźnika zerowego.
Poniżej przedstawiono implementację java.lang.String.valueOf zgodnie z opisem w źródle jdk8u25. Więc jak na mój komentarz, nie ma różnicy. Wywołuje „Object.toString”. W przypadku typów pierwotnych opakowuje go w postać obiektu i wywołuje na nim „toString”.
Zobacz poniżej:
/*
* 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);
}
Nie mogę dokładnie powiedzieć, na czym polega różnica, ale wydaje się, że istnieje różnica podczas pracy na poziomie bajtów. W następującym scenariuszu szyfrowania Object.toString () wygenerował wartość, której nie można było odszyfrować, podczas gdy String.valueOf () działało zgodnie z zamierzeniami ...
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[])a nie valueOf(Object). Zachowanie valueOf(char[])znacznie różni się od char[].toString(). Ale tak czy inaczej, ta odpowiedź nie jest apropos ponieważ dzwonisz inny przeciążenie na jednym pytaniem pyta o.
String.valueOfjest używane. W przypadku obiektów, które przesłaniają toString, myślę, że String.valueOf może to wywołać. Nie jestem pewien co do tej części.