String.valueOf () против Object.toString ()


132

В Java есть ли разница между String.valueOf(Object)и Object.toString()? Есть ли для них особые правила кода?


10
Примитивные типы не имеют "toString" ... поэтому String.valueOfиспользуется. Для объектов, которые переопределяют toString, я думаю, что String.valueOf может вызвать это вместо этого. Не уверен насчет этой части.
Брэндон

@Brandon Вы правы, он делает именно это, за исключением того, что nullсначала проверяет .
azurefrog

Первый комментарий здесь, я думаю, имеет наибольший смысл, если он правильный. Вы должны использовать String.valueOf в определенных ситуациях, когда целью является примитивный тип.
Донато

Ответы:


177

Согласно документации Java , String.valueOf()возвращает:

если аргумент равен null, то строка равна "null"; в противном случае obj.toString()возвращается значение.

Так что на самом деле не должно быть никакой разницы, кроме вызова дополнительного метода.

Кроме того, в случае Object#toString, если экземпляр есть null, NullPointerExceptionбудет брошен a , поэтому, возможно, это менее безопасно .

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
Это лучший ответ. Читайте и полагайтесь на javadocs, а не на код. (Код в принципе может отличаться для разных версий / выпусков Java.)
Stephen C

7
@Brandon - Неверно. Его нужно только изменить, если поведение изменится таким образом, что javadoc станет недействительным. 1) Шансы на то, что это произойдет для этого метода, НУЛЬ. Они не будут вносить изменения, которые требуют изменения спецификации, а если они это сделают, то они изменят спецификацию. 2) Это не отменяет мой совет. Если вы прочитаете javadoc, то увидите, что задокументированное поведение изменилось!
Stephen C

2
Разве метод, вызывающий исключение, не был бы более безопасным? Обычно, когда ваш код выдает исключение NullPointerException, это вроде как хорошо. В данный момент разработчику это может показаться неприятным («Ой, нет, теперь мне нужно вернуться и исправить мой код»), но, поскольку возникла ошибка, вы обнаружили, что вам нужно что-то исправить. В противном случае вы показываете «нуль» непосредственно пользователю и не получаете сообщения об ошибке, если вы явно не проверите его, что мне кажется менее безопасным.
Тим М.

1
Чтобы было ясно, вы не можете на самом деле звонить String.valueOf(null), это NPE. Он работает только для нулевых объектов.
Ноумен

1
Это не объяснение. String.valueOf(null)Фактически решает к valueOf(char[])перегрузке. Это потому, что char[]это более конкретный тип, чем Object.
Stephen C

17

Различия между String.valueOf (Object) и Object.toString ():

1) Если строка нулевая,

String.valueOf(Object)вернет null, тогда как Object::toString()вызовет исключение с нулевым указателем.

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) Подпись:

valueOf () класса String является статическим. тогда как метод toString () класса String нестатичен.

Подпись или синтаксис строкового метода valueOf () приведены ниже:

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)

Подпись или синтаксис строкового toString()метода приведены ниже:

public String toString()

13

В Java есть ли разница между String.valueOf (Object) и Object.toString ()?

Да. (И тем более, если учесть перегрузку!)

Как объясняется в javadoc , метод String.valueOf((Object) null)будет рассматривать как особый случай, valueOfи значение "null"будет возвращено. Напротив, null.toString()просто даст вам NPE.

перегрузка

Оказывается, String.valueOf(null)(обратите внимание на разницу!) Действительно дает NPE ... несмотря на javadoc. Объяснение неясное:

  1. Существует ряд перегрузок String.valueOf, но здесь важны две: String.valueOf(Object)и String.valueOf(char[]).

  2. В выражении применимыString.valueOf(null) обе эти перегрузки , поскольку присваивание совместимо с любым ссылочным типом.null

  3. При наличии двух или более применимых перегрузок JLS сообщает, что выбрана перегрузка для наиболее конкретного типа аргумента.

  4. Поскольку char[]это подтип Object, он более конкретен .

  5. Поэтому String.valueOf(char[])перегрузка называется.

  6. String.valueOf(char[])выдает NPE, если его аргумент является нулевым массивом. В отличие от этого String.valueOf(Object), это не рассматривается nullкак особый случай.

(Вы можете подтвердить это, используя javap -cдля проверки кода метода, который вызывает String.valueOf(null)вызов. Обратите внимание на перегрузку, которая используется для вызова.)

Другой пример valueOf(char[])еще яснее иллюстрирует разницу в перегрузке:

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

Есть ли для них особые правила кода?

Нет.

Используйте то, что лучше всего соответствует требованиям контекста, в котором вы его используете. (Вам нужно форматирование для работы null?)

Примечание: это не соглашение о коде. Это просто программирование на основе здравого смысла. Более важно, чтобы ваш код был правильным, чем следовать каким-то стилистическим соглашениям или догме "передовой практики".


Личное мнение:

Некоторые разработчики приобретают (IMO) дурную привычку «защищаться» от нулей. Итак, вы видите множество тестов на пустые значения и рассматриваете нули как особые случаи. Идея, кажется, состоит в том, чтобы предотвратить появление NPE.

Я думаю, что это плохая идея. В частности, я думаю, что это плохая идея, если то, что вы делаете, когда вы обнаруживаете, - nullэто попытки «исправить» ... без учета того, почему он там был null.

В общем, лучше вообще не nullбыть там ... если только это не nullимеет очень конкретного значения в вашем приложении или дизайне API. Таким образом, вместо того, чтобы избегать NPE с большим количеством защитного кодирования, лучше позволить NPE произойти, а затем отследить и исправить источник непредвиденного null, вызвавшего NPE.

Итак, как это применимо здесь?

Что ж, если вы думаете об этом, использование String.valueOf(obj) могло бы быть способом "исправления положения". Этого следует избегать. Если неожиданно objоказаться nullв контексте, лучше использовать obj.toString().


5

Большинство из них уже упоминалось в других ответах, но я просто добавляю его для полноты:

  1. Примитивы не имеют, так .toString()как они не являются реализацией Objectкласса -class, поэтому String.valueOfмогут использоваться только.
  2. String.valueOfпреобразует данный объект nullв String "null", тогда как .toString()вызовет NullPointerException.
  3. Компилятор будет использовать String.valueOfпо умолчанию, когда используется что-то вроде String s = "" + (...);. Вот почему в Object t = null; String s = "" + t;результате будет строка "null", а не NPE. РЕДАКТИРОВАТЬ: На самом деле он будет использовать StringBuilder.append, а не String.valueOf. Так что игнорируйте то, что я здесь сказал.

В дополнение к этому, вот пример использования, когда String.valueOfи .toString()имеют разные результаты:

Допустим, у нас есть такой общий метод:

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

И мы будем называть его с Integerтипом , как это: Main.<Integer>test().

Когда мы создаем String, String.valueOfон отлично работает:

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

Это будет выводиться testв STDOUT.

Однако с a .toString()это не сработает:

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

Это приведет к следующей ошибке:

java.lang.ClassCastException: class java.lang.Stringне может быть приведен к классуjava.lang.Integer

Попробуйте онлайн.

Что касается почему, я могу сослаться на этот отдельный вопрос и ответы на него . Вкратце, однако:

  • При использовании .toString()он сначала компилировать и оценивать объект, в котором приведение к T(который является Stringк Integerотлит в данном случае) приведет к ClassCastException.
  • При использовании String.valueOfон будет видеть общий файл, Tкак Objectво время компиляции, и даже не заботится о том, чтобы он был Integer. Таким образом, он будет приводить Objectк Object(что компилятор просто игнорирует). Затем он будет использовать String.valueOf(Object), что приведет к Stringожидаемому результату. Таким образом, даже несмотря на String.valueOf(Object)то, .toString()что внутри параметра будет выполняться a , мы уже пропустили приведение и обработали его как an Object, поэтому мы избежали того, ClassCastExceptionчто происходит с использованием .toString().

Просто подумал, что стоит упомянуть эту дополнительную разницу между String.valueOfи .toString()здесь.


В прошлый раз, когда я заботился об этом, это было бы около JDK 1.2, ("" + x)скомпилированное в String.valueOf(x), но для чего-то более сложного использовался StringBuffer(тогда у нас не было StringBuilder).
Нил

4

String.valueOf(Object)и Object.toString()буквально одно и то же.

Если вы посмотрите на реализацию String.valueOf (Object) , вы увидите, что String.valueOf(Object)это в основном просто нулевой безопасный вызов toString()соответствующего объекта:

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

Неправда, используйте как valueOf, так и toString в массиве char и полюбуйтесь.
Artanis

3

Наиболее важным отличием является способ обработки ссылок на пустые строки.

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

Когда аргумент равен null, String.valueOfвозвращает "null", но Object.toStringвыбрасывает NullPointerException, это единственная разница.


0

Есть еще одно важное различие между этими двумя методами: когда объект, который мы конвертируем, является массивом.

Когда вы конвертируете массив с помощью Object.toString (), вы получите какое-то значение мусора (@, за которым следует хэш-код массива).

Чтобы получить удобочитаемый toString (), вы должны использовать String.valueOf (char []); Пожалуйста, обратите внимание, что этот метод работает только для массива типа char. Я бы рекомендовал использовать Arrays.toString (Object []) для преобразования массивов в String.

Второе отличие заключается в том, что когда объект имеет значение NULL, ValueOf () возвращает String «null», а toString () возвращает исключение с нулевым указателем.


Привет, @Tom, это верно для массива любого типа, однако, если вы используете Arrays.toString (Object []), вы можете преобразовать массив любого типа в строку.
chintan thakker

Привет @Tom Object.toString (), возвращающий значение мусора, верно для массива любого типа, вы правы, что String.valueOf (Array) даст правильную строку только для массива типа char. Я должен был упомянуть, что спасибо, я его отредактирую.
chintan thakker

1
Это не мусорное значение, это имя класса и хэш-код ( JavaDoc ).
Tom

-1

Я не могу точно сказать, в чем разница, но кажется разница при работе на уровне байтов. В следующем сценарии шифрования Object.toString () выдал значение, которое не удалось расшифровать, тогда как String.valueOf () работал по назначению ...

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[])а не valueOf(Object). Поведение valueOf(char[])существенно отличается от char[].toString(). Но так или иначе, этот ответ не по поводу , потому что вы вызываете другую перегрузку в один Вопрос спрашивает о.
Стивен С.

-1

И в большинстве случаев лучше возвращать NPE, чем "нулевое" значение.


-2

Ниже показана реализация java.lang.String.valueOf, как описано в исходном коде jdk8u25. Итак, согласно моему комментарию, разницы нет. Он вызывает Object.toString. Для примитивных типов он оборачивает его в объектную форму и вызывает для него «toString».

Увидеть ниже:

/*
 * 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);
    }
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.