String.valueOf () vs Object.toString ()

132

Di Jawa, apakah ada perbedaan antara String.valueOf(Object)dan Object.toString()? Apakah ada konvensi kode khusus untuk ini?

MCMastery
sumber
10
Tipe primitif tidak memiliki "toString" .. begitu String.valueOfdigunakan. Untuk objek yang menggantikan toString, saya pikir String.valueOf mungkin menyebutnya sebagai gantinya. Tidak yakin tentang bagian itu.
Brandon
@ Brandon Anda benar, ia melakukan hal itu, kecuali memeriksa nullterlebih dahulu.
azurefrog
Komentar pertama di sini menurut saya paling masuk akal jika itu benar. Anda harus menggunakan String.valueOf dalam situasi tertentu di mana target adalah tipe primitif.
Donato

Jawaban:

177

Menurut dokumentasi Java , String.valueOf()pengembalian:

jika argumennya adalah null, maka string sama dengan "null"; jika tidak, nilai obj.toString()dikembalikan.

Jadi seharusnya tidak ada perbedaan kecuali untuk permohonan metode tambahan.

Juga, dalam kasus Object#toString, jika instansinya adalah null, NullPointerExceptionakan dilempar, jadi bisa dibilang, itu kurang aman .

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
} 
Kuba Rakoczy
sumber
6
Ini jawaban terbaik. Baca dan andalkan javadocs, bukan kode. (Pada prinsipnya kode bisa berbeda untuk versi / rilis yang berbeda dari Java.)
Stephen C
7
@Brandon - Salah. Itu hanya perlu berubah jika perilaku berubah dengan cara yang membatalkan javadoc. 1) Peluang yang terjadi untuk metode ini adalah NOL. Mereka tidak akan membuat perubahan yang menjamin perubahan dalam spesifikasi, dan jika mereka melakukannya maka mereka akan mengubah spesifikasi. 2) Itu tidak membatalkan saran saya. Jika Anda membaca javadoc, maka Anda akan melihat bahwa perilaku yang didokumentasikan telah berubah!
Stephen C
2
Bukankah metode yang melempar pengecualian lebih aman? Biasanya, ketika kode Anda melempar NullPointerException, itu semacam hal yang baik. Mungkin terasa tidak enak bagi pengembang saat ini ("aww, tidak, sekarang saya harus kembali dan memperbaiki kode saya"), tetapi karena kesalahan itu terjadi, Anda tahu Anda perlu memperbaiki sesuatu. Jika dibiarkan, Anda mengekspos "null" langsung ke pengguna dan tidak mendapatkan kesalahan yang dilaporkan kecuali Anda secara eksplisit memeriksa satu, yang menurut saya kurang aman.
Tim M.
1
Untuk lebih jelasnya, Anda tidak dapat benar-benar menelepon String.valueOf(null), itu adalah NPE. Ini hanya berfungsi untuk objek yang null.
Noumenon
1
Bukan itu penjelasannya. The String.valueOf(null)sebenarnya resolve ke valueOf(char[])overload. Ini karena char[]jenis yang lebih spesifik daripada Object.
Stephen C
17

Perbedaan antara String.valueOf (Object) dan Object.toString () adalah:

1) Jika string adalah nol,

String.valueOf(Object)akan kembali null, sedangkan Object::toString()akan membuang pengecualian pointer nol.

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) Tanda tangan:

metode valueOf () dari kelas String bersifat statis. sedangkan metode toString () dari kelas String tidak statis.

Tanda tangan atau sintaks dari metode valueOf () string diberikan di bawah ini:

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)

Tanda tangan atau sintaksis toString()metode string diberikan di bawah ini:

public String toString()
Shipra Sharma
sumber
13

Di Jawa, apakah ada perbedaan antara String.valueOf (Object) dan Object.toString ()?

Iya. (Dan lebih dari itu jika Anda mempertimbangkan kelebihan!)

Seperti yang dijelaskan javadoc , String.valueOf((Object) null)akan diperlakukan sebagai kasus khusus oleh valueOfmetode dan nilai "null"dikembalikan. Sebaliknya, null.toString()hanya akan memberi Anda NPE.

Kelebihan beban

Ternyata String.valueOf(null)(perhatikan perbedaannya!) Memang memberikan NPE ... terlepas dari javadoc. Penjelasannya tidak jelas:

  1. Ada sejumlah kelebihan String.valueOf, tetapi ada dua yang relevan di sini: String.valueOf(Object)dan String.valueOf(char[]).

  2. Dalam ekspresi String.valueOf(null), kedua kelebihan tersebut berlaku , karena nullpenugasan tersebut kompatibel dengan jenis referensi apa pun.

  3. Ketika ada dua atau lebih kelebihan yang berlaku , JLS mengatakan bahwa kelebihan untuk jenis argumen paling spesifik dipilih.

  4. Karena char[]ini adalah subtipe dari Object, itu lebih spesifik .

  5. Oleh karena itu String.valueOf(char[])kelebihan disebut.

  6. String.valueOf(char[])melempar NPE jika argumennya adalah array nol. Tidak seperti String.valueOf(Object)itu, itu tidak diperlakukan nullsebagai kasus khusus.

(Anda dapat mengonfirmasi ini dengan menggunakan javap -cuntuk memeriksa kode metode yang memiliki String.valueOf(null)panggilan. Amati kelebihan beban yang digunakan untuk panggilan tersebut.)

Contoh lain menggambarkan perbedaan dalam valueOf(char[])kelebihan beban bahkan lebih jelas:

char[] abc = new char[]('a', 'b', 'c');
System.out.println(String.valueOf(abc));  // prints "abc"
System.out.println(abc.toString());       // prints "[C@...."

Apakah ada konvensi kode khusus untuk ini?

Tidak.

Gunakan mana yang paling sesuai dengan persyaratan konteks di mana Anda menggunakannya. (Apakah Anda membutuhkan pemformatan untuk bekerja null?)

Catatan: itu bukan konvensi kode. Itu hanya pemrograman akal sehat. Lebih penting bahwa kode Anda benar daripada mengikuti beberapa konvensi gaya atau dogma "praktik terbaik".


Opini pribadi:

Beberapa pengembang memperoleh (IMO) kebiasaan buruk "membela" terhadap nol. Jadi Anda melihat banyak tes untuk nulls, dan memperlakukan nulls sebagai kasus khusus. Idenya tampaknya mencegah NPE terjadi.

Saya pikir ini ide yang buruk. Secara khusus, saya pikir itu adalah ide yang buruk jika apa yang Anda lakukan ketika Anda menemukan nulladalah mencoba untuk "membuat yang baik" ... tanpa pertimbangan mengapa ada di nullsana.

Secara umum, lebih baik untuk menghindari nullkeberadaan di tempat pertama ... kecuali jika nullmemiliki arti yang sangat spesifik dalam aplikasi atau desain API Anda. Jadi, daripada menghindari NPE dengan banyak pengkodean defensif, lebih baik membiarkan NPE terjadi, dan kemudian melacak dan memperbaiki sumber yang tidak terduga nullyang memicu NPE.

Jadi bagaimana ini berlaku di sini?

Nah, jika Anda memikirkannya, menggunakan String.valueOf(obj) bisa menjadi cara "membuat yang baik". Itu harus dihindari. Jika tidak terduga objberada nulldalam konteks, lebih baik digunakan obj.toString().

Stephen C
sumber
5

Sebagian besar telah disebutkan oleh jawaban lain, tetapi saya hanya menambahkannya untuk kelengkapan:

  1. Primitif tidak memiliki a .toString()karena mereka bukan implementasi dari Object-class, jadi hanya String.valueOfdapat digunakan.
  2. String.valueOfakan mengubah objek yang diberikan nullke String "null", sedangkan .toString()akan melempar a NullPointerException.
  3. Compiler akan digunakan String.valueOfsecara default ketika sesuatu seperti String s = "" + (...);digunakan. Itulah sebabnya Object t = null; String s = "" + t;akan menghasilkan String "null", dan bukan NPE. EDIT: Sebenarnya, itu akan menggunakan StringBuilder.append, bukan String.valueOf. Jadi abaikan apa yang saya katakan di sini.

Selain itu, di sini sebenarnya kasus penggunaan di mana String.valueOfdan .toString()memiliki hasil yang berbeda:

Katakanlah kita memiliki metode generik seperti ini:

public static <T> T test(){
  String str = "test";
  return (T) str;
}

Dan kita akan menyebutnya dengan Integertipe seperti ini: Main.<Integer>test().

Ketika kami membuat sebuah String dengan String.valueOfitu berfungsi dengan baik:

String s1 = String.valueOf(Main.<Integer>test());
System.out.println(s1);

Ini akan menghasilkan testSTDOUT.

Dengan .toString()Namun, itu tidak akan berhasil:

String s2 = (Main.<Integer>test()).toString();
System.out.println(s2);

Ini akan menghasilkan kesalahan berikut:

java.lang.ClassCastException: kelas java.lang.Stringtidak dapat dilemparkan ke kelasjava.lang.Integer

Cobalah online.

Mengenai alasannya, saya dapat merujuk pada pertanyaan yang terpisah ini dan jawabannya . Singkatnya:

  • Saat menggunakannya .toString(), pertama-tama akan mengkompilasi dan mengevaluasi objek, di mana pemain yang akan T(yang merupakan pemain Stringuntuk Integerkasus ini) akan menghasilkan ClassCastException.
  • Saat menggunakannya String.valueOfakan melihat generik Tsebagai Objectselama kompilasi dan bahkan tidak peduli itu menjadi Integer. Jadi itu akan melemparkan Objectke Object(yang mengabaikan kompiler). Kemudian akan digunakan String.valueOf(Object), menghasilkan Stringseperti yang diharapkan. Jadi meskipun String.valueOf(Object)akan melakukan .toString()pada parameter secara internal, kami sudah melewatkan para pemain dan diperlakukan seperti Object, jadi kami telah menghindari ClassCastExceptionyang terjadi dengan penggunaan .toString().

Hanya berpikir itu layak menyebutkan perbedaan tambahan antara String.valueOfdan di .toString()sini juga.

Kevin Cruijssen
sumber
Terakhir kali saya peduli tentang ini, yang akan berada di sekitar JDK 1.2, ("" + x)dikompilasi String.valueOf(x), tetapi sesuatu yang lebih rumit menggunakan StringBuffer(kami tidak memiliki StringBuilderitu).
Neil
4

String.valueOf(Object)dan Object.toString()secara harfiah adalah hal yang sama.

Jika Anda melihat implementasi String.valueOf (Object) , Anda akan melihat bahwa String.valueOf(Object)pada dasarnya hanya permohonan null-safe dari toString()objek yang sesuai:

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();
}
azurefrog
sumber
Tidak benar, gunakan kedua valueOf dan toString pada array char dan pesta mata Anda.
Artanis
3

Perbedaan paling penting adalah cara mereka menangani referensi String nol.

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
Abdullah Khan
sumber
1

Ketika argumen adalah null, String.valueOfpengembalian "null", tetapi Object.toStringmelempar NullPointerException, itulah satu-satunya perbedaan.

Everv0id
sumber
0

Ada satu lagi perbedaan utama antara kedua metode ini ketika objek yang kita konversi adalah array.

Ketika Anda mengubah array menggunakan Object.toString () Anda akan mendapatkan beberapa jenis nilai sampah (@ diikuti oleh kode hash array).

Untuk mendapatkan toString () yang dapat dibaca manusia, Anda harus menggunakan String.valueOf (char []); harap dicatat bahwa metode ini hanya berfungsi untuk array tipe char. Saya akan merekomendasikan menggunakan Arrays.toString (Object []) untuk mengubah array ke String.

Perbedaan kedua adalah ketika objeknya nol, ValueOf () mengembalikan sebuah String "null", sedangkan toString () akan mengembalikan pengecualian pointer nol.

chintan thakker
sumber
Hai @Tom ini berlaku untuk array jenis apa pun, namun jika Anda menggunakan Arrays.toString (Obyek []), Anda dapat mengubah array jenis apa pun menjadi string.
chintan thakker
Hai @Tom Object.toString () mengembalikan nilai sampah benar untuk array jenis apa pun, Anda benar bahwa String.valueOf (Array) akan memberikan string yang benar hanya untuk array tipe char. Saya seharusnya mengatakan bahwa, terima kasih, saya akan mengeditnya.
chintan thakker
1
Itu bukan nilai sampah, itu adalah classname dan kode hash ( JavaDoc ).
Tom
-1

Saya tidak bisa mengatakan dengan tepat apa perbedaannya tetapi tampaknya ada perbedaan ketika beroperasi pada level byte. Dalam skenario enkripsi berikut, Object.toString () menghasilkan nilai yang tidak dapat didekripsi sedangkan String.valueOf () berfungsi seperti yang dimaksudkan ...

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()
Chris Walters
sumber
Mengapa gagal apa masalahnya?
Yousha Aleayoub
Penjelasannya adalah bahwa Anda sebenarnya menelepon valueOf(char[])daripada valueOf(Object). Perilaku valueOf(char[])berbeda secara signifikan terhadap char[].toString(). Namun demikian, jawaban ini bukan sesuai karena Anda memanggil kelebihan yang berbeda dengan pertanyaan yang ditanyakan.
Stephen C
-2

Di bawah ini menunjukkan implementasi untuk java.lang.String.valueOf seperti yang dijelaskan dalam sumber untuk jdk8u25. Jadi sesuai komentar saya, tidak ada perbedaan. Itu panggilan "Object.toString". Untuk tipe primitif, ia membungkusnya dalam bentuk objeknya dan memanggil "toString" di atasnya.

Lihat di bawah:

/*
 * 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);
    }
Brandon
sumber