【问题标题】:Explicit vs implicit call of toStringtoString 的显式与隐式调用
【发布时间】:2010-09-24 15:02:59
【问题描述】:

当我想要一些关于对象的调试信息时,我曾经使用隐式调用 toString,因为如果对象为空,它不会抛出异常。

例如:

System.out.println("obj: "+obj);

代替:

System.out.println("obj: "+obj.toString());

除了 null case 有什么不同吗?
后一种情况是否可行,而前一种情况则不行?

编辑:
在隐式调用的情况下到底做了什么?

【问题讨论】:

    标签: java tostring


    【解决方案1】:

    差别不大。使用更短且工作更频繁的那个。

    如果您出于其他原因确实想获取对象的字符串值,并且希望它对 null 友好,请执行以下操作:

    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"
      • 原始类型使用盒装类型构造函数new Boolean(X) 或其他方式进行转换
      • toString() 被调用(或等效)
      • 如果toString()结果null,使用"null"
      • 连接字符串。

      【讨论】:

      • 您清单上的第 4 项引起了我的兴趣。对于不是字符串的东西,它会附加 String.valueOf(String.valueOf(ob))。我想它很便宜并且符合要求。
      • 嘿-漂亮。老实说,在我查看规范之前我也不知道——区别并不重要。一个很好的例子,说明为什么我总是尽可能地使用主要来源。
      【解决方案3】:

      没有区别,就像你说的那样,空安全。总是喜欢前者而不是后者。

      【讨论】:

        【解决方案4】:

        实际上,如果你的不变量说对象永远不应该为空,那没关系。所以这取决于你是否接受 obj 为空。

        【讨论】:

          【解决方案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
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-02-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多