В Java есть ли разница между String.valueOf(Object)
и Object.toString()
? Есть ли для них особые правила кода?
null
сначала проверяет .
В Java есть ли разница между String.valueOf(Object)
и Object.toString()
? Есть ли для них особые правила кода?
null
сначала проверяет .
Ответы:
Согласно документации 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
}
String.valueOf(null)
, это NPE. Он работает только для нулевых объектов.
String.valueOf(null)
Фактически решает к valueOf(char[])
перегрузке. Это потому, что char[]
это более конкретный тип, чем Object
.
Различия между 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()
В Java есть ли разница между String.valueOf (Object) и Object.toString ()?
Да. (И тем более, если учесть перегрузку!)
Как объясняется в javadoc , метод String.valueOf((Object) null)
будет рассматривать как особый случай, valueOf
и значение "null"
будет возвращено. Напротив, null.toString()
просто даст вам NPE.
Оказывается, String.valueOf(null)
(обратите внимание на разницу!) Действительно дает NPE ... несмотря на javadoc. Объяснение неясное:
Существует ряд перегрузок String.valueOf
, но здесь важны две: String.valueOf(Object)
и String.valueOf(char[])
.
В выражении применимыString.valueOf(null)
обе эти перегрузки , поскольку присваивание совместимо с любым ссылочным типом.null
При наличии двух или более применимых перегрузок JLS сообщает, что выбрана перегрузка для наиболее конкретного типа аргумента.
Поскольку char[]
это подтип Object
, он более конкретен .
Поэтому String.valueOf(char[])
перегрузка называется.
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()
.
Большинство из них уже упоминалось в других ответах, но я просто добавляю его для полноты:
.toString()
как они не являются реализацией Object
класса -class, поэтому String.valueOf
могут использоваться только.String.valueOf
преобразует данный объект null
в String "null"
, тогда как .toString()
вызовет NullPointerException
.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
: classjava.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()
здесь.
("" + x)
скомпилированное в String.valueOf(x)
, но для чего-то более сложного использовался StringBuffer
(тогда у нас не было StringBuilder
).
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();
}
Наиболее важным отличием является способ обработки ссылок на пустые строки.
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
Есть еще одно важное различие между этими двумя методами: когда объект, который мы конвертируем, является массивом.
Когда вы конвертируете массив с помощью Object.toString (), вы получите какое-то значение мусора (@, за которым следует хэш-код массива).
Чтобы получить удобочитаемый toString (), вы должны использовать String.valueOf (char []); Пожалуйста, обратите внимание, что этот метод работает только для массива типа char. Я бы рекомендовал использовать Arrays.toString (Object []) для преобразования массивов в String.
Второе отличие заключается в том, что когда объект имеет значение NULL, ValueOf () возвращает String «null», а toString () возвращает исключение с нулевым указателем.
Я не могу точно сказать, в чем разница, но кажется разница при работе на уровне байтов. В следующем сценарии шифрования 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()
. Но так или иначе, этот ответ не по поводу , потому что вы вызываете другую перегрузку в один Вопрос спрашивает о.
Ниже показана реализация 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);
}
String.valueOf
используется. Для объектов, которые переопределяют toString, я думаю, что String.valueOf может вызвать это вместо этого. Не уверен насчет этой части.