Как распечатать мой объект Java, не получив "SomeType @2f92e0f4"?

У меня есть класс, определяемый следующим образом:

public class Person {
  private String name;

  // constructor and getter/setter omitted
}

Я попытался напечатать экземпляр моего класса:

System.out.println(myPerson);

но я получил следующий вывод: com.foo.Person@2f92e0f4.

Аналогичная ситуация произошла, когда я попытался напечатать массив объектов Person:

Person[] people = //...
System.out.println(people); 

Я получил результат: [Lcom.foo.Person;@28a418fc

Что означает этот вывод? Как изменить этот вывод, чтобы он содержал имя моего лица? И как мне печатать коллекции моих объектов?

Примечание: это предполагается каноническим Q & A об этом предмете.

+226
19 мар. '15 в 8:59
источник поделиться
9 ответов

Фон

Все объекты Java имеют метод toString(), который вызывается при попытке распечатать объект.

System.out.println(myObject);  // invokes myObject.toString()

Этот метод определен в классе Object (суперкласс всех объектов Java). Метод Object.toString() возвращает довольно уродливую строку, состоящую из имени класса, символа @ и hashcode объекта в шестнадцатеричном формате. Код для этого выглядит так:

// Code of Object.toString()
public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

Результат, например com.foo.MyType@2f92e0f4, может быть объяснен как:

  • com.foo.MyType - имя класса, то есть класс MyType в пакете com.foo.
  • @ - соединяет строку вместе
  • 2f92e0f4 хэш-код объекта.

Название классов массивов выглядит немного иначе, что хорошо объясняется в Javadocs для Class.getName(). Например, [Ljava.lang.String означает:

  • [ - одномерный массив (в отличие от [[ или [[[ и т.д.)
  • L - массив содержит класс или интерфейс
  • java.lang.String - тип объектов в массиве

Настройка вывода

Чтобы напечатать что-то другое, когда вы вызываете System.out.println(myObject), вы должны override метод toString() в своем классе. Вот простой пример:

public class Person {

  private String name;

  // constructors and other methods omitted

  @Override
  public String toString() {
    return name;
  }
}

Теперь, если мы напечатаем Person, мы увидим их имя, а не com.foo.Person@12345678.

Имейте в виду, что toString() - это всего лишь один способ преобразования объекта в строку. Как правило, этот вывод должен полностью описывать ваш объект в ясной и сжатой форме. Лучшим toString() для нашего класса Person может быть:

@Override
public String toString() {
  return getClass().getSimpleName() + "[name=" + name + "]";
}

Что бы напечатать, например, Person[name=Henry]. Это действительно полезная часть данных для отладки/тестирования.

Если вы хотите сосредоточиться только на одном аспекте своего объекта или включить много джазового форматирования, вам может быть лучше определить отдельный метод, например, String toElegantReport() {...}.


Автоматическое создание выходного сигнала

Многие IDE предлагают поддержку автоматического создания метода toString() на основе полей в классе. Например, docs для Eclipse и IntelliJ.

Некоторые популярные библиотеки Java также предлагают эту функцию. Вот некоторые примеры:


Печать групп объектов

Итак, вы создали приятный toString() для своего класса. Что произойдет, если этот класс помещается в массив или коллекцию?

Массивы

Если у вас есть массив объектов, вы можете вызвать Arrays.toString(), чтобы создать простое представление содержимого массива. Например, рассмотрим этот массив объектов Person:

Person[] people = { new Person("Fred"), new Person("Mike") };
System.out.println(Arrays.toString(people));

// Prints: [Fred, Mike]

Примечание: это вызов статического метода с именем toString() в классе Arrays, который отличается от того, что мы обсуждали выше.

Если у вас есть многомерный массив, вы можете использовать Arrays.deepToString() для достижения того же типа выход.

Коллекции

В большинстве коллекций будет создан довольно простой вывод, основанный на вызове .toString() для каждого элемента.

List<Person> people = new ArrayList<>();
people.add(new Person("Alice"));
people.add(new Person("Bob"));    
System.out.println(people);

// Prints [Alice, Bob]

Итак, вам просто нужно убедиться, что элементы списка определяют хороший toString(), как обсуждалось выше.

+316
19 мар. '15 в 8:59
источник

Я думаю, что apache предоставляет лучший класс util, который предоставляет функцию для получения строки

ReflectionToStringBuilder.toString(object)
+35
15 апр. '15 в 13:31
источник

Каждый класс в java имеет метод toString() по умолчанию, который вызывается System.out.println(), если вы передаете ему некоторый объект класса. Когда вы пытаетесь напечатать объект класса, метод System.out.println() вызовет toString() класса, который возвращает hashcode классаName @этого объекта.

{
    SomeClass sc = new SomeClass();
    // Class @ followed by hashcode of object in Hexadecimal
    System.out.println(sc);
}

Вы можете переопределить метод toString класса для получения другого вывода. См. Этот пример

class A {
    String s = "I am just a object";
    @Override
    public String toString()
    {
        return s;
    }
}

class B {
    public static void main(String args[])
    {
        A obj = new A();
        System.out.println(obj);
    }
}
+23
19 мар. '15 в 10:04
источник

В Eclipse, Пойдите в свой класс, Щелкните правой кнопкой мыши- > source- > Generate toString();

Он переопределит метод toString() и напечатает объект этого класса.

+8
21 апр. '16 в 13:45
источник

По умолчанию каждый объект в Java имеет метод toString() который выводит ObjectType @HashCode.

Если вам нужна более значимая информация, вам необходимо переопределить метод toString() в вашем классе.

public class Person {
  private String name;

  // constructor and getter/setter omitted

  // overridding toString() to print name
  public String toString(){
     return name;  
  }
}

Теперь, когда вы печатаете объект person с помощью System.out.prtinln(personObj); он будет печатать имя человека вместо имени класса и хэш-кода.

Во втором случае, когда вы пытаетесь распечатать массив, он печатает [Lcom.foo.Person;@28a418fc тип массива и hashcode.


Если вы хотите напечатать имена людей, существует множество способов.

Вы можете написать свою собственную функцию, которая выполняет итерацию каждого человека и печатает

void printPersonArray(Person[] persons){
    for(Person person: persons){
        System.out.println(person);
    }
}

Вы можете распечатать его с помощью Arrays.toString(). Это кажется мне самым простым.

 System.out.println(Arrays.toString(persons));
 System.out.println(Arrays.deepToString(persons));  // for nested arrays  

Вы можете напечатать его java 8 способом (используя потоки и ссылку на метод).

 Arrays.stream(persons).forEach(System.out::println);

Могут быть и другие способы. Надеюсь это поможет. :)

+4
02 дек. '17 в 16:23
источник

Если вы прямо напечатаете любой объект Person, он будет ClassName@HashCode к коду.

в вашем случае com.foo.Person@2f92e0f4 печатается. Где Person - класс, к которому принадлежит объект, и 2f92e0f4 - hashCode объекта.

public class Person {
  private String name;

  public Person(String name){
  this.name = name;
  }
  // getter/setter omitted

   @override
   public String toString(){
        return name;
   }
}

Теперь, если вы попытаетесь использовать объект Person, тогда он напечатает имя

Class Test
 {
  public static void main(String... args){
    Person obj = new Person("YourName");
    System.out.println(obj.toString());
  }
}
+3
06 мая '16 в 11:22
источник

В intellij вы можете автоматически генерировать метод toString, нажимая alt + inset, а затем выбрав toString(), вот выкл для тестового класса:

public class test  {
int a;
char b;
String c;
Test2 test2;

@Override
public String toString() {
    return "test{" +
            "a=" + a +
            ", b=" + b +
            ", c='" + c + '\'' +
            ", test2=" + test2 +
            '}';
 }
}

Как вы можете видеть, он генерирует String путем конкатенации нескольких атрибутов класса, для примитивов он будет печатать свои значения, а для ссылочных типов он будет использовать свой тип класса (в данном случае - для строкового метода Test2).

+3
28 июл. '16 в 6:00
источник

Если вы посмотрите на класс Object (класс родителей всех классов в Java), реализация метода toString() -

    public String toString() {
       return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }

всякий раз, когда вы печатаете какой-либо объект в Java, тогда toString() будет вызывать. Теперь это зависит от вас, если вы переопределите toString(), тогда ваш метод вызовет вызов метода класса объекта.

+2
27 мар. '17 в 6:21
источник
Arrays.deepToString(arrayOfObject)

Выше функции печатайте массив объекта с разными примитивами.

[[AAAAA, BBBBB], [6, 12], [2003-04-01 00:00:00.0, 2003-10-01 00:00:00.0], [2003-09-30 00:00:00.0, 2004-03-31 00:00:00.0], [Interim, Interim], [2003-09-30, 2004-03-31]];
-2
07 июл. '17 в 14:06
источник

Посмотрите другие вопросы по меткам или Задайте вопрос