String.valueOf () ile Object.toString () karşılaştırması


132

Java'da String.valueOf(Object)ve arasında herhangi bir fark var Object.toString()mı? Bunlar için özel bir kod kuralı var mı?


10
İlkel türlerin "toString" i yoktur .. bu String.valueOfnedenle kullanılır. ToString'i geçersiz kılan nesneler için String.valueOf'un bunu çağırabileceğini düşünüyorum. Yine de o kısımdan emin değilim.
Brandon

@Brandon Haklısınız, tam olarak bunu yapıyor, nullilk önce kontrol etmesi dışında .
azurefrog

Buradaki ilk yorum bence doğruysa çok mantıklı. Hedefin ilkel bir tür olduğu belirli durumlarda String.valueOf kullanmanız gerekir.
Donato

Yanıtlar:


177

Göre Java belgeleri , String.valueOf()döner:

argüman ise null, o zaman bir dizge eşittir "null"; aksi takdirde değeri obj.toString()döndürülür.

Bu nedenle, ek bir yöntem çağrısı dışında gerçekten bir fark olmamalıdır.

Ayrıca, Object#toStringörnek olması durumunda null, a NullPointerExceptionatılır, bu yüzden tartışmalı bir şekilde daha az güvenlidir .

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
} 

6
Bu en iyi cevap. Kodu değil javadoc'ları okuyun ve bunlara güvenin. (Kod, Java'nın farklı sürümleri / sürümleri için prensipte farklı olabilir.)
Stephen C

7
@Brandon - Yanlış. Yalnızca davranış javadoc'u geçersiz kılacak şekilde değişirse değiştirilmesi gerekir . 1) Bu yöntem için gerçekleşme şansı SIFIR. Onlar spec bir değişiklik garanti bir değişiklik yapmaz, ve eğer o zaman olurdu spec değiştirin. 2) Tavsiyemi geçersiz kılmaz. Javadoc'u okursanız, belgelenen davranışın değiştiğini göreceksiniz!
Stephen C

2
İstisnayı atan yöntem daha güvenli olmaz mıydı? Genellikle, kodunuz bir NullPointerException oluşturduğunda, bu iyi bir şeydir. Şu anda geliştirici için iyi hissettirmeyebilir ("aww, hayır, şimdi geri dönüp kodumu düzeltmem gerekiyor"), ancak hata atıldığı için bir şeyi düzeltmeniz gerektiğini anladınız. Diğer taraftan, "boş" u doğrudan kullanıcıya ifşa ediyorsunuz ve açıkça birini kontrol etmediğiniz sürece bir hata bildirilmiyor, ki bu bana daha az güvenli görünüyor.
Tim M.

1
Açık olmak gerekirse, aslında String.valueOf(null)arayamazsınız, bu bir NPE'dir. Yalnızca boş olan nesneler için çalışır.
Noumenon

1
Açıklama bu değil. String.valueOf(null)Aslında olarak çözümlenir valueOf(char[])aşırı. Bunun nedeni char[], daha özel bir tür olmasıdır Object.
Stephen C

17

String.valueOf (Object) ve Object.toString () arasındaki farklar şunlardır:

1) string boş ise,

String.valueOf(Object)dönecek null, oysa Object::toString()boş bir işaretçi istisnası atacak.

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) İmza:

String sınıfının valueOf () yöntemi statiktir. oysa String sınıfının toString () yöntemi statik değildir.

Dizenin valueOf () yönteminin imzası veya sözdizimi aşağıda verilmiştir:

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)

Dizenin toString()yönteminin imzası veya sözdizimi aşağıda verilmiştir:

public String toString()

13

Java'da, String.valueOf (Object) ve Object.toString () arasında herhangi bir fark var mı?

Evet. (Ve dahası, aşırı yüklemeyi düşünürseniz!)

Olarak javadoc açıklar String.valueOf((Object) null)ile özel bir durum olarak kabul edilir valueOfbir yöntem ve değer "null"iade edilir. Aksine, null.toString()size sadece bir NPE verecektir.

fazla yükleme

O çıkıyor String.valueOf(null)(! Farka dikkat) yapar javadoc rağmen ... Bir NPE ver. Açıklama belirsiz:

  1. Çok sayıda aşırı yükleme var String.valueOf, ancak burada ilgili olan iki tane var: String.valueOf(Object)ve String.valueOf(char[]).

  2. İfadede String.valueOf(null), atama herhangi bir referans tipiyle uyumlu olduğundan , bu aşırı yüklerin her ikisi de uygulanabilirnull .

  3. İki veya daha fazla uygulanabilir aşırı yük olduğunda, JLS, en spesifik bağımsız değişken türü için aşırı yüklemenin seçildiğini söyler .

  4. Yana char[]bir alt tipi olan Object, öyle daha spesifik .

  5. Bu nedenle String.valueOf(char[])aşırı yükleme denir.

  6. String.valueOf(char[])argümanı boş bir diziyse bir NPE atar. Aksine String.valueOf(Object), nullözel bir durum olarak ele alınmaz .

( Çağrısı javap -colan bir yöntemin kodunu incelemek için kullanarak bunu doğrulayabilirsiniz String.valueOf(null). Çağrı için kullanılan aşırı yüklemeyi gözlemleyin.)

Başka bir örnek, valueOf(char[])aşırı yükteki farkı daha da net bir şekilde göstermektedir:

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

Bunlar için özel bir kod kuralı var mı?

Hayır.

Kullanmakta olduğunuz bağlamın gereksinimlerine en uygun olanı kullanın. ( Çalışmak için biçimlendirmeye ihtiyacınız varnull mı?)

Not: Bu bir kod kuralı değildir. Bu sadece sağduyu programlamasıdır. Kodunuzun doğru olması, bazı biçimsel kuralları veya "en iyi uygulama" dogmaları izlemekten daha önemlidir .


Kişisel görüş:

Bazı geliştiriciler (IMO) boşlara karşı "savunma" gibi kötü bir alışkanlık edinirler. Böylece, boş değerler için çok sayıda test görüyorsunuz ve boş değerleri özel durumlar olarak değerlendiriyorsunuz. Fikir, NPE'nin olmasını engelliyor gibi görünüyor.

Bunun kötü bir fikir olduğunu düşünüyorum. Özellikle, a'yı bulduğunuzda yaptığınız şeyin null, neden orada olduğunu düşünmeden ... "iyiye gitmeye" çalışmaksa ... kötü bir fikir olduğunu düşünüyorum null.

Genel olarak, nullilk etapta orada olmaktan kaçınmak daha iyidir ... nulluygulamanızda veya API tasarımınızda çok özel bir anlamı yoksa. Bu nedenle, çok sayıda savunma kodlamasıyla NPE'den kaçınmak yerine, NPE'nin gerçekleşmesine izin vermek ve ardından nullNPE'yi tetikleyen beklenmedik kaynağın izini sürmek ve düzeltmek daha iyidir .

Peki bu burada nasıl geçerli?

Peki, düşünürseniz, kullanmak "iyileştirmenin" bir yolu String.valueOf(obj) olabilir . Bundan kaçınılması gerekir. Bağlamda objolması beklenmiyorsa null, kullanmak daha iyidir obj.toString().


5

Birçoğundan başka cevaplardan bahsedilmişti, ancak ben sadece bütünlük için ekliyorum:

  1. İlkellerin .toString()bir Object-class uygulaması olmadıklarından, sadece String.valueOfkullanılabilirler.
  2. String.valueOfbelirli bir nesneyi nullString'e dönüştürecek "null", oysa .toString()bir NullPointerException.
  3. Derleyici, String.valueOfbenzeri bir String s = "" + (...);şey kullanıldığında varsayılan olarak kullanacaktır . Bu nedenle Object t = null; String s = "" + t;, "null"NPE ile değil , Dize ile sonuçlanacaktır . DÜZENLEME: Aslında, kullanacak StringBuilder.append, değil String.valueOf. Bu yüzden burada söylediklerimi görmezden gelin.

Bunların yanı sıra, burada bir kullanım örneği aslında String.valueOfve .toString()farklı sonuçlar vardır:

Diyelim ki bunun gibi genel bir yöntemimiz var:

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

Ve biz bir ile arayacağım Integerböyle türü: Main.<Integer>test().

Bir String oluşturduğumuzda String.valueOfiyi çalışıyor:

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

Bu testSTDOUT'a çıktı verecektir .

Bununla .toString()birlikte, işe yaramaz:

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

Bu, aşağıdaki hataya neden olur:

java.lang.ClassCastException: sınıf java.lang.Stringsınıfa dönüştürülemezjava.lang.Integer

Çevrimiçi deneyin.

Nedenine gelince, bu ayrı soruya ve cevaplarına başvurabilirim . Kısacası, ancak:

  • Kullanıldığında .toString()ilk derlemek ve döküm nesnesini değerlendirecek T(bir olduğu Stringiçin Integer, bu durumda döküm) neden olur ClassCastException.
  • Kullanırken String.valueOfjeneriği derleme sırasındaki Tgibi görür Objectve bir Integer. Böylece bir Objectto Object(derleyicinin görmezden geldiği) atacaktır . Daha sonra kullanacak ve beklendiği gibi String.valueOf(Object)a sonucunu verecektir String. Yani String.valueOf(Object)will .toString(), dahili olarak parametre üzerinde bir yapsa da, atlamayı zaten atladık ve bir gibi muamele Objectgördük, bu yüzden ClassCastExceptionkullanımıyla meydana gelenlerden kaçındık .toString().

Sadece buradaki String.valueOfve arasındaki bu ek farktan bahsetmeye değer olduğunu düşündüm .toString().


Bunu en son umursadığımda, JDK 1.2 civarında ("" + x)derlenmişti String.valueOf(x), ama daha karmaşık olan herhangi bir şey a kullanıyordu StringBuffer( StringBuildero zamanlar sahip değildik ).
Neil

4

String.valueOf(Object)ve Object.toString()kelimenin tam anlamıyla aynı şeydir.

String.valueOf (Object) uygulamasına bakarsanız, bunun String.valueOf(Object)temelde toString()uygun nesnenin boş güvenlikli bir çağrısı olduğunu göreceksiniz :

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();
}

Doğru değil, bir karakter dizisinde hem valueOf hem de toString'i kullanın ve gözlerinize ziyafet çekin.
Artanis

3

En önemli fark, boş Dize referanslarını işleme şekilleridir.

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

1

Argüman olduğu zaman null, String.valueOfgeri dönüşler "null"ama Object.toStringfırlatır NullPointerException, tek fark budur.


0

İki yöntem arasında önemli bir fark daha var, dönüştürdüğümüz nesnenin bir dizi olması.

Object.toString () kullanarak bir diziyi dönüştürdüğünüzde, bir tür çöp değeri (@ ardından dizi hashcode'u) elde edersiniz.

İnsan tarafından okunabilir bir toString () elde etmek için String.valueOf (char []) kullanmanız gerekir; plz, bu yöntemin yalnızca char türündeki Array için çalıştığını unutmayın. Dizileri String'e dönüştürmek için Arrays.toString (Object []) kullanmanızı tavsiye ederim.

İkinci fark, nesne null olduğunda, ValueOf () bir String "null" döndürürken, toString () null işaretçi istisnası döndürür.


Merhaba @Tom bu, herhangi bir türden bir dizi için doğrudur, Ancak Arrays.toString (Object []) kullanıyorsanız, herhangi bir türden bir diziyi dizeye dönüştürebilirsiniz.
chintan thakker

Merhaba @Tom Object.toString () herhangi bir türden bir dizi için bir çöp değeri döndürmek doğrudur, String.valueOf (Array) yalnızca bir char türü dizisi için doğru bir dize verecektir. Şunu söylemeliydim, teşekkürler, düzenleyeceğim.
chintan thakker

1
Bu bir anlamsız değer değil, sınıf adı ve karma koddur ( JavaDoc ).
Tom

-1

Farkın ne olduğunu tam olarak söyleyemem ama bayt seviyesinde çalışırken bir fark var gibi görünüyor. Aşağıdaki şifreleme senaryosunda Object.toString (), şifresi çözülemeyen bir değer üretirken String.valueOf () amaçlandığı gibi çalıştı ...

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()

Neden başarısız oldu? sorun ne?
Yousha Aleayoub

Açıklama, aslında aramak valueOf(char[])yerine aradığınızdır valueOf(Object). Davranışı valueOf(char[])önemli ölçüde farklıdır char[].toString(). Ancak her iki durumda da, bu cevap uygun değildir çünkü Sorunun sorduğu sorudan farklı bir aşırı yükleme çağırıyorsunuz.
Stephen C

-1

Ve çoğu durumda, "boş" değer yerine NPE döndürmek daha iyidir


-2

Aşağıda, jdk8u25 için kaynakta açıklandığı gibi java.lang.String.valueOf için uygulama gösterilmektedir. Yani benim yorumuma göre, hiçbir fark yok. "Object.toString" çağırır. İlkel türler için, onu nesne biçiminde sarar ve üzerinde "toString" çağırır.

Aşağıya bakınız:

/*
 * 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);
    }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.