Явный vs неявный вызов toString
Я использовал неявный вызов toString, когда вам нужна некоторая отладочная информация об объекте, потому что в случае, если объект имеет значение null, он не генерирует исключение.
Например:
System.out.println("obj: "+obj);
вместо:
System.out.println("obj: "+obj.toString());
Есть ли какая-либо разница, кроме нулевого случая?
Может ли последний случай работать, когда первый не делает?
Edit:
Что именно делается, в случае неявного вызова?
Ответы
Ответ 1
Там небольшая разница. Используйте ту, которая короче и работает чаще.
Если вы действительно хотите получить строковое значение объекта по другим причинам и хотите, чтобы он был нулевым, сделайте следующее:
String s = String.valueOf(obj);
Изменить. Вопрос был расширен, поэтому я продолжу свой ответ.
В обоих случаях они компилируются примерно так:
System.out.println(new StringBuilder().append("obj: ").append(obj).toString());
Если ваш toString()
неявный, вы увидите, что во втором добавлении.
Если вы посмотрите на исходный код на java, вы увидите, что StringBuilder.append(Object)
выглядит так:
public StringBuilder append(Object obj) {
return append(String.valueOf(obj));
}
где String.valueOf
выглядит следующим образом:
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
Теперь, если вы toString()
сами, вы обходите нулевую проверку и стек стека и переходите прямо к этому в StringBuilder
:
public StringBuilder append(String str) {
super.append(str);
return this;
}
Итак... очень похожие вещи происходят в обоих случаях. Просто нужно немного поработать.
Ответ 2
Как говорили другие, используйте метод "" + obj
.
Согласно Java Language Spec:
- Если этот термин равен нулю, используйте
"null"
- Примитивные типы преобразуются с использованием конструктора boxed type
new Boolean(X)
или любого другого
-
toString()
вызывается (или эквивалентно)
- Если результат
toString()
равен null
, используйте "null"
- Объединить строки.
Ответ 3
Никакой разницы, кроме, как вы говорите, нет нулевой безопасности. Всегда предпочитайте первое для последнего.
Ответ 4
Собственно, если ваш инвариант говорит, что объект никогда не должен быть нулевым, это не имеет значения. Это зависит от того, принимаете ли вы obj равным null.
Ответ 5
Очень просто написать общий ссылочный тип.
class ref
{
static public class Reference<T>
{
private T value;
public Reference(T value) { set(value); }
public Reference() { set(null); }
public void set (T value) { this.value = value; }
public T get () { return this.value; }
public String toString() { return String.valueOf(this.value); }
}
static void fillString (Reference<String> str)
{
str.set("foo");
}
public static void main (String[] args)
{
Reference<String> str = new Reference<String>("");
fillString(str);
System.out.println (str);
}
}
Запуск он дает требуемый вывод:
javac ref.java && java ref
foo