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

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

public class Person {
  private String name;

  // constructor and getter/setter omitted
}

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

System.out.println(myPerson);

но я получил следующий вывод: [email protected].

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

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

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

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

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

+278
источник поделиться
10 ответов

Фон

Все объекты 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());
}

Результат, например [email protected], может быть объяснен как:

  • 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, мы увидим их имя, а не [email protected].

Имейте в виду, что 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(), как обсуждалось выше.

+367
источник

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

ReflectionToStringBuilder.toString(object)
+45
источник

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

{
    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);
    }
}
+31
источник

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

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

+10
источник

В 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).

+4
источник

По умолчанию каждый объект в 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
источник

Я предпочитаю использовать служебную функцию, которая использует GSON для десериализации объекта Java в строку JSON.

/**
 * This class provides basic/common functionalities to be applied on Java Objects.
 */
public final class ObjectUtils {

    private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();

    private ObjectUtils() {
         throw new UnsupportedOperationException("Instantiation of this class is not permitted in case you are using reflection.");
    }

    /**
     * This method is responsible for de-serializing the Java Object into Json String.
     *
     * @param object Object to be de-serialized.
     * @return String
     */
    public static String deserializeObjectToString(final Object object) {
        return GSON.toJson(object);
    }
}
+4
источник

Если вы прямо напечатаете любой объект Person, он будет [email protected] к коду.

в вашем случае [email protected] печатается. Где 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
источник

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

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

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

+2
источник
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
источник

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