Почему метод 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(", ");
}
}