【问题标题】:How does (this) overriding tostring method for LinkedList class work?(this)覆盖 LinkedList 类的 tostring 方法是如何工作的?
【发布时间】:2019-08-18 17:04:22
【问题描述】:

我创建了一个class Test,将class Pair 对象存储在库中定义的链表数据结构中。要打印 Pair 类对象,我在 pair 类中重写了方法,它的工作原理如下所示 -

import java.util.LinkedList;

class Test{
    static LinkedList<Pair> list=new LinkedList<Pair>();
    public static void main(String[] args){
        list.add(new Pair(31,78));
        list.add(new Pair(89,67));
        list.add(new Pair(90,43));

        System.out.println(list);
    }
}

class Pair{
    int x;
    int y;
    Pair(int m, int n){
        x=m;
        y=n;
    }
    @Override
    public String toString(){
        return "{ "+ this.x + ", " +this.y+" }";
    }
}

输出 -

[{ 2, 4 }, { 6, 3 }, { 12, 6 }]

我怀疑toString() 方法-

  • 打印链接列表时内部会发生什么?
  • 如果我将一些整数存储在链表中,是否会调用 Integer 类的 toString() 方法?

【问题讨论】:

    标签: java inheritance overriding tostring


    【解决方案1】:

    LinkedList&lt;E&gt;.toString()的实现继承自AbstractCollection&lt;E&gt;documented 是这样的:

    返回此集合的字符串表示形式。字符串表示由集合元素的列表组成,按其迭代器返回的顺序排列,用方括号 ("[]") 括起来。相邻元素由字符", "(逗号和空格)分隔。元素通过String.valueOf(Object) 转换为字符串。

    所以String.valueOf 在每个元素上都被调用——这反过来又会为任何非空元素调用Object.toString()。在您的情况下,您已经在 Pair 中覆盖了它,所以这就是所谓的。

    如果你在Pair.toString添加一些日志,像这样:

    public String toString(){
        String ret = "{ "+ this.x + ", " +this.y+" }";
        System.out.println("toString called: returning " + ret;
        return ret;
    }
    

    ...您可以看到它被调用(或者您可以使用调试器)。是的,如果列表包含整数,则列表的字符串表示将是 "[1, 2, 3, 4, 5]" 或其他。 (String.valueOf 可能被优化为直接处理数字类型,但逻辑上它会调用Integer 中的toString() 覆盖。)

    【讨论】:

      【解决方案2】:

      这里是LinkedList的源代码:

      http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/java/util/LinkedList.java

      哪个(经过几个步骤)最终实现了 AbstractCollection

      http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/java/util/AbstractCollection.java

      正如您所见,toString 的源代码在这里:

          public String toString() {
              Iterator<E> it = iterator();
              if (! it.hasNext())
                  return "[]";
      
              StringBuilder sb = new StringBuilder();
              sb.append('[');
              for (;;) {
                  E e = it.next();
                  sb.append(e == this ? "(this Collection)" : e);
                  if (! it.hasNext())
                      return sb.append(']').toString();
                  sb.append(',').append(' ');
              }
          }
      

      现在我们需要找出在使用.append() 添加eStringBuilder 做了什么

      可在 StringBuilder 源代码中找到

      http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/java/lang/StringBuilder.java

          @Override
          public StringBuilder append(Object obj) {
              return append(String.valueOf(obj));
          }
      

      现在的问题是,String.valueOf 做了什么?

      这里是来源:

      http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/java/lang/String.java

          public static String valueOf(Object obj) {
              return (obj == null) ? "null" : obj.toString();
          }
      

      所以你的问题的答案是:是的,它会调用IntegertoString 方法。

      【讨论】:

        【解决方案3】:

        对象类是否使用端类的toString()方法打印

        不,println 方法调用list 对象toString() 方法。

        LinkedList 有一个toString() 实现,它调用列表中所有对象的toString() 方法来构建[item1, item2, ...] 字符串。

        这当然意味着您的toString() 方法是由LinkedList 调用的,而不是由Object 类调用的。

        如果我将一些整数存储在链表中,会调用IntegertoString() 方法吗?

        是的。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-01-11
          • 2019-08-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-04-21
          • 2018-01-10
          相关资源
          最近更新 更多