简体   繁体   English

为什么toString()方法在Java中的Array和ArrayList对象之间的工作方式不同

[英]Why toString() method works differently between Array and ArrayList object in Java

    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);

For list [a, b, c] is output while for array some address is output. 对于list [a, b, c]输出,而对于array输出一些地址。 When we want to output the array values, we can use Arrays.toString(array); 当我们想输出array值时,我们可以使用Arrays.toString(array); which works just like list . 它就像list一样工作。

I just wonder why we can't call toString() directly on array to get the values. 我只是想知道为什么我们不能直接在array上调用toString()来获取值。 Isn't it more intuitive and convenient to do so? 这样做不是更直观和方便吗? What results in the different treatments on Array and ArrayList ? 什么导致ArrayArrayList的不同处理?

The main difference between an array and an arraylist is that an arraylist is a class that is written in Java and has its own implementation (including the decision to override toString ) whereas arrays are part of the language specification itself. 数组和arraylist之间的主要区别在于arraylist是一个用Java编写的类,它有自己的实现(包括重写toString的决定),而数组是语言规范本身的一部分。 In particular, the JLS 10.7 states: 特别是, JLS 10.7规定:

The members of an array type are all of the following: 数组类型的成员是以下所有成员:

  • The public final field length 公共最终字段长度
  • The public method clone, which overrides the method of the same name in class Object and throws no checked exceptions. 公共方法clone,它覆盖Object类中的同名方法,并且不会抛出任何已检查的异常。
  • All the members inherited from class Object; 所有成员都继承自Object类; the only method of Object that is not inherited is its clone method. 唯一没有继承的Object方法是它的clone方法。

In other words the language specification prevents the toString method of an array to be overriden and it therefore uses the default implementation defined in Object which prints the class name and hashcode. 换句话说,语言规范会阻止数组的toString方法被覆盖,因此它使用Object中定义的默认实现来打印类名和哈希码。

Why this decision has been made is a question that should probably be asked to the designers of the language... 为什么做出这个决定是一个问题,应该向语言的设计者提出......

I just wonder why we can't call toString() directly on array to get the values. 我只是想知道为什么我们不能直接在数组上调用toString()来获取值。

Actually toString method is called on the array object. 实际上在数组对象上调用toString方法。 But, since array type does not override toString method from Object class, so default implementation of toString is invoked, that returns the representation of the form that you see. 但是,由于数组类型不会覆盖Object类的toString方法,因此调用toString默认实现,返回您看到的表单的表示形式。

The representation is of the form: - 代表形式如下: -

[typeOfArray@hashCode

In your case it's something like: - 在你的情况下,它是这样的: -

[Ljava.lang.String;@3e25a5

Whereas, in case of ArrayList instances, the overriden toString method in ArrayList class is invoked. 然而,在ArrayList实例的情况下,调用ArrayList类中的重写toString方法。

The short answer is because toString is defined in a few different places, with different behaviours. 简短的回答是因为toString是在几个不同的地方定义的,具有不同的行为。

The Arrays class defines toString as a static method, to be invoked like Arrays类将toString定义为静态方法,可以调用

Arrays.toString(arr_name);

But the Arrays class also inherits the non-static method toString from the Object class. 但是Arrays类还从Object类继承了非静态方法toString。 So if called on an instance, it invokes Object.toString which returns a string representation of the object (eg: [Ljava.lang.Object;@4e44ac6a) 因此,如果在实例上调用它,它会调用Object.toString,它返回对象的字符串表示形式(例如:[Ljava.lang.Object; @ 4e44ac6a)

So Arrays.toString() and MyObject.toString() are calling different methods with the same name. 所以Arrays.toString()和MyObject.toString()正在调用具有相同名称的不同方法。

The ArrayList class inherits toString from the AbstractCollection class, where it is a non static method, so can be called on the object like: ArrayList类从AbstractCollection类继承toString,它是一个非静态方法,因此可以在对象上调用,如:

MyArrayList.toString();

Because it's a string representation of a collection and not an object, the result is the values in a readable format like [one, two]. 因为它是集合的字符串表示而不是对象,所以结果是可读格式的值,如[one,two]。

Because when you print toString() , it will by default print className@HashCode . 因为当你打印toString() ,默认会打印className@HashCode

So, when you print array then above will be printed. 因此,当您打印array ,将打印上面的内容。

But ArrayList is extened by AbstractCollection class and where the toString() method is overriden as below 但是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(' ');
        }
    }

which prints the readable format of the ArrayList object. 它打印ArrayList对象的可读格式。

This is the toString method call for ArrayList. 这是ArrayList的toString方法调用。 But for Arrays you cant find such. 但是对于Arrays,你无法找到它。

 /**
 * 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(' ');
    }
}

For array toString() method it prints the memory address. 对于array toString()方法,它打印内存地址。 But in ArrayList this class overrides Object toString() method . 但是在ArrayList这个类重写了Object toString()方法。

toString() implementation of ArrayList 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(", ");
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM