【问题标题】:Why toString() method works differently between Array and ArrayList object in Java为什么 toString() 方法在 Java 中的 Array 和 ArrayList 对象之间的工作方式不同
【发布时间】:2012-11-26 15:38:35
【问题描述】:
    String[] array = {"a","c","b"};
    ArrayList<String> list = new ArrayList<String>();
    list.add("a");
    list.add("b");
    list.add("c");
    System.out.println(array);
    System.out.println(list);

对于list,输出[a, b, c],而对于array,输出一些地址。当我们要输出array 的值时,我们可以使用Arrays.toString(array);,它的工作原理与list 类似。

我只是想知道为什么我们不能直接在array 上调用toString() 来获取值。这样做不是更直观方便吗?对ArrayArrayList 进行不同处理的结果是什么?

【问题讨论】:

    标签: java arrays arraylist tostring


    【解决方案1】:

    简短的回答是因为 toString 是在几个不同的地方定义的,具有不同的行为。

    Arrays 类将 toString 定义为静态方法,调用方式类似于

    Arrays.toString(arr_name);
    

    但是Arrays类也继承了Object类的非静态方法toString。因此,如果在实例上调用,它会调用 Object.toString,它返回对象的字符串表示形式(例如:[Ljava.lang.Object;@4e44ac6a)

    所以 Arrays.toString() 和 MyObject.toString() 调用同名的不同方法。

    ArrayList类继承自AbstractCollection类的toString,它是一个非静态方法,所以可以像这样在对象上调用:

    MyArrayList.toString();
    

    因为它是集合而不是对象的字符串表示形式,所以结果是可读格式的值,例如 [one, two]。

    【讨论】:

      【解决方案2】:

      我只是想知道为什么我们不能直接在数组上调用 toString() 来获取 值。

      其实toString方法是在数组对象上调用的。但是,由于数组类型不会覆盖 Object 类中的 toString 方法,因此会调用 toString 的默认实现,这会返回您所看到的表单的表示形式。

      表示形式为:-

      [typeOfArray@hashCode
      

      在你的情况下是这样的:-

      [Ljava.lang.String;@3e25a5
      

      而在ArrayList 实例的情况下,将调用ArrayList 类中覆盖的toString 方法。

      【讨论】:

        【解决方案3】:

        这是 ArrayList 的 toString 方法调用。但是对于数组你找不到这样的。

         /**
         * Returns a string representation of this collection.  The string
         * representation consists of a list of the collection's elements in the
         * order they are returned by its iterator, enclosed in square brackets
         * (<tt>"[]"</tt>).  Adjacent elements are separated by the characters
         * <tt>", "</tt> (comma and space).  Elements are converted to strings as
         * by {@link String#valueOf(Object)}.
         *
         * @return a string representation of this collection
         */
        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(' ');
            }
        }
        

        【讨论】:

          【解决方案4】:

          对于array toString() 方法,它会打印内存地址。但是在ArrayList 中,这个类覆盖了Object toString() 方法。

          toString() 的 ArrayList 实现

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

          【讨论】:

            【解决方案5】:

            因为当你打印toString()时,它会默认打印className@HashCode

            所以,当你打印array 时,上面的内容就会被打印出来。

            但是ArrayListAbstractCollection 类扩展,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(' ');
                    }
                }
            

            打印ArrayList对象的可读格式。

            【讨论】:

              【解决方案6】:

              数组和数组列表之间的主要区别在于,数组列表是一个用 Java 编写的类,并且有自己的实现(包括覆盖toString 的决定),而数组是语言规范本身的一部分。特别是,JLS 10.7 声明:

              数组类型的成员都有以下几种:

              • 公共最终字段长度
              • 公共方法clone,覆盖Object类中的同名方法,不抛出检查异常。
              • 继承自Object类的所有成员; Object 唯一不被继承的方法是它的 clone 方法。

              换句话说,语言规范阻止数组的toString 方法被覆盖,因此它使用Object 中定义的默认实现,打印类名和哈希码。

              为什么做出这个决定是一个应该问语言设计者的问题......

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2013-04-14
                • 1970-01-01
                • 1970-01-01
                • 2018-06-23
                • 2023-02-25
                • 1970-01-01
                • 1970-01-01
                • 2013-12-12
                相关资源
                最近更新 更多