【问题标题】:Why is toString in class A evoked even though it is not called?为什么即使没有调用 A 类中的 toString 也会被调用?
【发布时间】:2017-08-19 23:47:06
【问题描述】:
public class Test {
    public static void main(String[] args) {
        Object a1 = new A();
        Object a2 = new Object();
        System.out.println(a1);
        System.out.println(a2);
    }
}

class A {
    int x;

    public String toString() {
        return "A's x is " + x;
    }
}

输出

A 的 x 为 0

java.lang.Object@1edf1c96

打印 a1 时,会调用类 A 中的 toString() 方法,而无需显式调用。你能解释一下这是怎么发生的吗?

【问题讨论】:

  • println 还应该打印什么?

标签: java string class tostring


【解决方案1】:

toString()println(Object) 隐式调用。显然,因为它需要显示String,而toString() 保证为所有对象返回某种 形式的String 表示。

【讨论】:

  • 你能解释一下这是怎么发生的吗?编译器怎么知道A类中的toString方法会返回一个字符串?
  • 因为在Object.toString()中是这样定义的。
  • @Enzio:因为这是由它的类型定义的。你为什么认为你写public String toString() {...因为你有一个合同它返回一个String
【解决方案2】:

如果要将任何对象表示为字符串,toString() 方法就应运而生了。

toString() 方法返回对象的字符串表示形式。

如果您打印任何对象,java 编译器会在内部调用该对象的toString() 方法。因此,重写 toString() 方法,返回所需的输出,它可以是对象的状态等。取决于您的实现。

通过重写Object类的toString()方法,我们可以返回对象的值,所以我们不需要写太多代码。

【讨论】:

    【解决方案3】:

    toString() 方法在每个Object 中定义。它的默认行为是返回该对象的字符串表示形式,例如"java.lang.Object@1edf1c96"

    在您的A 类中,您刚刚通过重新定义toString() 方法将这种行为替换为新行为(“重新定义”意味着在子类中使用相同的签名再次定义该方法)。

    这称为覆盖

    当你打印一个对象时,println() 方法会盲目地调用对象的toString() 方法,而不知道(或关心)它是否被重新定义。

    【讨论】:

      【解决方案4】:

      您可以在PrintStream.println(Object) 的文档中阅读:

      public void println(Object x)

         打印一个对象,然后终止该行。这 方法的行为就好像它 调用 print(Object) 然后 println().

         参数:
      x - 要打印的对象。

      现在如果我们看一下PrintStream.print(Object),我们会看到:

      public void print(Object obj)

         打印一个对象。由 生成的字符串 String.valueOf(Object) 方法被翻译成字节根据 平台的默认字符编码,这些字节被写入 与write(int) 方法完全相同。

         参数:
      obj - 要打印的对象

      现在可以看到,内部调用了String.valueOf(object),其定义为:

      public static String valueOf(Object obj)

         返回对象的字符串表示 论据。

         参数:
      obj - 一个对象。
      返回:
            如果 参数是null,然后是等于"null"的字符串; 否则, 返回obj.toString() 的值。

      也就是说,如果你写这样的东西:

      System.out.println(foo);
      

      你实际上已经写了一些等价的东西:

      System.out.print(foo);
      System.out.println();
      

      进一步扩展为:

      System.out.print(String.valueOf(foo));
      System.out.println();
      

      扩展为:

      if(foo == null) {
          System.out.print("null");
      } else {
          System.out.print(foo.toString());
      }
      System.out.println();

      或者说得更清楚。在PrintStream的代码中,你会看到类似:

      public class PrintStream {
      
          // ...
      
          public void println(Object x) {
              this.print(x);
              this.println();
          }
      
          public void print(Object obj) {
              String result = String.valueOf(obj);
              // ... do something with result (print it to the stream)
          }
      
      }
      

      String 你会发现类似的东西:

      public class String {
      
          // ...
      
          public static String valueOf (Object obj) {
              if(obj == null) {
                  return "null";
              } else {
                  return obj.toString();
              }
          }
      
      }

      【讨论】:

        猜你喜欢
        • 2021-04-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-04-30
        • 2015-08-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多