Почему метод toString() работает по-разному между объектами Array и ArrayList в 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);

Для list [a, b, c] выводится, а для array выводится какой-то адрес. Когда мы хотим вывести значения array, мы можем использовать Arrays.toString(array);, который работает так же, как list.

Мне просто интересно, почему мы не можем вызвать toString() непосредственно на array, чтобы получить значения. Не более ли интуитивно и удобно это делать? Что приводит к различным методам лечения array и ArrayList?

Ответ 1

Основное различие между массивом и arraylist заключается в том, что arraylist - это класс, написанный на Java и имеющий свою собственную реализацию (включая решение переопределить toString), тогда как массивы являются частью самой спецификации языка. В частности, JLS 10.7 заявляет:

Элементы типа массива являются следующими:

  • Публичная конечная длина поля
  • Открытый общедоступный метод клонирования, который переопределяет метод с тем же именем в объекте класса и не исключает проверенных исключений.
  • Все члены, унаследованные от класса Object; единственным методом Object, который не унаследован, является его метод clone.

Другими словами, спецификация языка предотвращает переопределение метода toString массива и поэтому использует реализацию по умолчанию, определенную в Object, которая печатает имя класса и хэш-код.

Почему это решение было принято, это вопрос, который, вероятно, следует задать разработчикам языка...

Ответ 2

Мне просто интересно, почему мы не можем вызвать toString() непосредственно на массив, чтобы получить значения.

Фактически метод toString вызывается в объекте массива. Но поскольку тип массива не переопределяет метод toString из класса Object, поэтому вызывается реализация по умолчанию toString, которая возвращает представление формы, которую вы видите.

Представление имеет вид: -

[[email protected]

В вашем случае это что-то вроде: -

[Ljava.lang.String;@3e25a5

В то время как в случае экземпляров ArrayList вызывается метод overriden toString в классе ArrayList.

Ответ 3

Короткий ответ заключается в том, что toString определяется в нескольких разных местах с различным поведением.

Класс Arrays определяет toString как статический метод, вызываемый как

Arrays.toString(arr_name);

Но класс Arrays также наследует нестатический метод toString из класса Object. Поэтому, если вызывается в экземпляре, он вызывает Object.toString, который возвращает строковое представление объекта (например: [Ljava.lang.Object; @4e44ac6a)

Итак, Arrays.toString() и MyObject.toString() вызывают разные методы с тем же именем.

Класс ArrayList наследует toString из класса AbstractCollection, где он является нестационарным методом, поэтому его можно вызвать на объекте, например:

MyArrayList.toString();

Поскольку это строковое представление коллекции, а не объекта, результатом являются значения в читаемом формате, например [один, два].

Ответ 4

Потому что, когда вы печатаете toString(), по умолчанию будет печать [email protected].

Итак, когда вы печатаете array, тогда будет напечатано выше.

Но ArrayList расширяется классом AbstractCollection и где метод 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.

Ответ 5

Это вызов метода toString для ArrayList. Но для массивов вы не можете найти таких.

 /**
 * Returns a string representation of this collection.  The string
 * representation consists of a list of the collection 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(' ');
    }
}

Ответ 6

Для метода 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(", ");
    }
}