Как распечатать мой объект 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 об этом предмете.
Ответы
Ответ 1
Фон
Все объекты 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()
, как обсуждалось выше.
Ответ 2
Я думаю, что apache предоставляет лучший класс util, который предоставляет функцию для получения строки
ReflectionToStringBuilder.toString(object)
Ответ 3
Каждый класс в 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);
}
}
Ответ 4
В Eclipse,
Пойдите в свой класс,
Щелкните правой кнопкой мыши- > source- > Generate toString()
;
Он переопределит метод toString()
и напечатает объект этого класса.
Ответ 5
В 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).
Ответ 6
По умолчанию каждый объект в 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);
Могут быть и другие способы. Надеюсь это поможет. :)
Ответ 7
Я предпочитаю использовать служебную функцию, которая использует 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);
}
}
Ответ 8
Если вы прямо напечатаете любой объект 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());
}
}
Ответ 9
Если вы посмотрите на класс Object (класс родителей всех классов в Java), реализация метода toString() -
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
всякий раз, когда вы печатаете какой-либо объект в Java, тогда toString() будет вызывать. Теперь это зависит от вас, если вы переопределите toString(), тогда ваш метод вызовет вызов метода класса объекта.
Ответ 10
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]];