¿Cómo imprimo mi objeto Java sin obtener “SomeType @ 2f92e0f4”?

Tengo una clase definida de la siguiente manera:

public class Person { private String name; // constructor and getter/setter omitted } 

Traté de imprimir una instancia de mi clase:

 System.out.println(myPerson); 

pero obtuve el siguiente resultado: com.foo.Person@2f92e0f4 .

Algo similar sucedió cuando traté de imprimir una matriz de objetos Person :

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

[Lcom.foo.Person;@28a418fc el resultado: [Lcom.foo.Person;@28a418fc

¿Qué significa esta salida? ¿Cómo cambio esta salida para que contenga el nombre de mi persona? ¿Y cómo imprimo colecciones de mis objetos?

Nota : esto está pensado como preguntas y respuestas canónicas sobre este tema.

Fondo

Todos los objetos Java tienen un método toString() , que se invoca cuando intenta imprimir el objeto.

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

Este método se define en la clase Object (la superclase de todos los objetos Java). El método Object.toString() devuelve una cadena bastante fea, compuesta por el nombre de la clase, un símbolo @ y el código hash del objeto en hexadecimal. El código para esto se ve así:

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

Un resultado como com.foo.MyType@2f92e0f4 se puede explicar como:

  • com.foo.MyType : el nombre de la clase, es decir, la clase es MyType en el paquete com.foo .
  • @ – une la cadena
  • 2f92e0f4 el hashcode del objeto.

El nombre de las clases de matriz se ve un poco diferente, lo que se explica bien en los Javadocs para Class.getName() . Por ejemplo, [Ljava.lang.String significa:

  • [ – una matriz unidimensional (a diferencia de [[ o [[[ etc.)]
  • L – la matriz contiene una clase o interfaz
  • java.lang.String : el tipo de objetos en la matriz

Personalizar la salida

Para imprimir algo diferente cuando llama a System.out.println(myObject) , debe anular el método toString() en su propia clase. Aquí hay un ejemplo simple:

 public class Person { private String name; // constructors and other methods omitted @Override public String toString() { return name; } } 

Ahora, si imprimimos una Person , vemos su nombre en lugar de com.foo.Person@12345678 .

Tenga en cuenta que toString() es solo una forma de convertir un objeto a una cadena. Normalmente, esta salida debe describir completamente su objeto de una manera clara y concisa. Una mejor toString() para nuestra clase Person podría ser:

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

Que imprimiría, por ejemplo, Person[name=Henry] . Esa es una pieza de datos realmente útil para la depuración / prueba.

Si desea enfocarse solo en un aspecto de su objeto o incluir un montón de formateo llamativo, es mejor que defina un método diferente en su lugar, por ejemplo, String toElegantReport() {...} .


Generación automática de la salida

Muchos IDE ofrecen soporte para autogenerar un método toString() basado en los campos de la clase. Ver documentos para Eclipse e IntelliJ , por ejemplo.

Varias bibliotecas populares de Java también ofrecen esta característica. Algunos ejemplos incluyen:

  • ToStringBuilder de Apache Commons Lang

  • MoreObjects.ToStringHelper de Google Guava

  • Anotación @ToString del Proyecto Lombok


Imprimir grupos de objetos

Así que has creado un buen toString() para tu clase. ¿Qué sucede si esa clase se coloca en una matriz o una colección?

Arrays

Si tiene una matriz de objetos, puede llamar a Arrays.toString() para producir una representación simple de los contenidos de la matriz. Por ejemplo, considere esta matriz de objetos Person :

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

Nota: esta es una llamada a un método estático llamado toString() en la clase Arrays, que es diferente a lo que hemos estado discutiendo arriba.

Si tiene una matriz multidimensional , puede usar Arrays.deepToString() para lograr el mismo tipo de salida.

Colecciones

La mayoría de las colecciones producirán una salida bonita basada en llamar a .toString() en cada elemento.

 List people = new ArrayList<>(); people.add(new Person("Alice")); people.add(new Person("Bob")); System.out.println(people); // Prints [Alice, Bob] 

Entonces solo necesita asegurarse de que los elementos de su lista definan un buen toString() como se discutió anteriormente.

Creo que apache proporciona una mejor clase util que proporciona una función para obtener la cadena

 ReflectionToStringBuilder.toString(object) 

Cada clase en Java tiene el método toString() forma predeterminada, que System.out.println() llama si le pasa algún objeto de una clase. Cuando intente imprimir el objeto de una clase, el método System.out.println() llamará a toString() de la clase que devuelve el className @ hashcode de ese objeto.

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

Puede anular el método toString de una clase para obtener resultados diferentes. Mira este ejemplo

 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); } } 

En Eclipse, vaya a su clase, haga clic derecho-> source-> Generate toString() ;

toString() método toString() e imprimirá el objeto de esa clase.

Por defecto, cada Objeto en Java tiene el método toString() que emite ObjectType @ HashCode.

Si desea información más significativa, debe anular el método toString() en su clase.

 public class Person { private String name; // constructor and getter/setter omitted // overridding toString() to print name public String toString(){ return name; } } 

Ahora cuando imprime el objeto persona usando System.out.prtinln(personObj); imprimirá el nombre de la persona en lugar del nombre de clase y el código hash.

En su segundo caso, cuando intenta imprimir la matriz, imprime [Lcom.foo.Person;@28a418fc el tipo de matriz y su [Lcom.foo.Person;@28a418fc .


Si desea imprimir los nombres de las personas, hay muchas maneras.

Puede escribir su propia función que itera a cada persona e imprime

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

Puede imprimirlo usando Arrays.toString (). Esto me parece lo más simple.

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

Puede imprimirlo en formato java 8 (utilizando flujos y referencia de método).

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

Puede haber otras formas también. Espero que esto ayude. 🙂

Si imprime directamente cualquier objeto de Persona, se llamará ClassName@HashCode al Código.

En su caso, se imprime com.foo.Person@2f92e0f4 . Donde Person es una clase a la que pertenece el objeto y 2f92e0f4 es hashCode del Objeto.

 public class Person { private String name; public Person(String name){ this.name = name; } // getter/setter omitted @override public String toString(){ return name; } } 

Ahora, si intenta usar el objeto de Person , imprimirá el nombre

 Class Test { public static void main(String... args){ Person obj = new Person("YourName"); System.out.println(obj.toString()); } } 

En intellij puedes generar automáticamente el método toString presionando alt + insert y luego seleccionando toString () aquí hay una salida para una clase de prueba:

 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 + '}'; } } 

Como puede ver, genera una Cadena al concatenar, varios atributos de la clase, para las primitivas imprimirá sus valores y para los tipos de referencia utilizará su tipo de clase (en este caso, el método de cadena de Test2).

Si observa la clase Object (clase Parent de todas las clases en Java), la implementación del método toString () es

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

cada vez que imprima cualquier objeto en Java, se llamará a toString (). Ahora depende de usted anular toString (), entonces su método llamará a otra llamada de método de clase Object.

 Arrays.deepToString(arrayOfObject) 

Sobre la función print array de objeto de diferentes primitivas.

 [[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]];