Come posso stampare il mio object Java senza ottenere “SomeType @ 2f92e0f4”?

Ho una class definita come segue:

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

Ho provato a stampare un’istanza della mia class:

 System.out.println(myPerson); 

ma ho ottenuto il seguente output: [email protected] .

Una cosa simile è accaduta quando ho provato a stampare un array di oggetti Person :

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

Ho ottenuto l’output: [Lcom.foo.Person;@28a418fc

Cosa significa questo output? Come cambio questa uscita in modo che contenga il nome della mia persona? E come posso stampare le raccolte dei miei oggetti?

Nota : questo è inteso come una domanda e risposta canonica su questo argomento.

sfondo

Tutti gli oggetti Java hanno un metodo toString() , che viene invocato quando si tenta di stampare l’object.

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

Questo metodo è definito nella class Object (la superclass di tutti gli oggetti Java). Il metodo Object.toString() restituisce una stringa abbastanza brutta, composta dal nome della class, un simbolo @ e il codice hash dell’object in esadecimale. Il codice per questo assomiglia a:

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

Un risultato come [email protected] può quindi essere spiegato come:

  • com.foo.MyType : il nome della class, ovvero la class è MyType nel pacchetto com.foo .
  • @ – unisce la stringa insieme
  • 2f92e0f4 il codice hash dell’object.

Il nome delle classi di array ha un aspetto leggermente diverso, che è spiegato bene in Javadocs per Class.getName() . Ad esempio, [Ljava.lang.String significa:

  • [ – una matrice monodesmensionale (al contrario di [[ o [[[ ecc.)
  • L – la matrice contiene una class o un’interfaccia
  • java.lang.String : il tipo di oggetti nella matrice

Personalizzazione dell’output

Per stampare qualcosa di diverso quando si chiama System.out.println(myObject) , è necessario sovrascrivere il metodo toString() nella propria class. Ecco un semplice esempio:

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

Ora se stampiamo una Person , vediamo il loro nome piuttosto che [email protected] .

toString() che toString() è solo un modo per convertire un object in una stringa. In genere questo output dovrebbe descrivere completamente il tuo object in modo chiaro e conciso. Un migliore toString() per la nostra class Person potrebbe essere:

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

Quale stamperebbe, per esempio, Person[name=Henry] . Questa è una porzione di dati davvero utile per il debug / test.

Se si desidera concentrarsi su un solo aspetto del proprio object o includere molta formattazione jazz, potrebbe essere preferibile definire un metodo separato, ad esempio String toElegantReport() {...} .


Auto-generazione dell’output

Molti IDE supportano la generazione automatica di un metodo toString() , basato sui campi della class. Vedi documenti per Eclipse e IntelliJ , per esempio.

Diverse librerie Java popolari offrono questa funzionalità. Alcuni esempi includono:

  • ToStringBuilder di Apache Commons Lang

  • MoreObjects.ToStringHelper da Google Guava

  • @ToString annotazione da Project Lombok


Stampa di gruppi di oggetti

Quindi hai creato un bel toString() per la tua class. Cosa succede se tale class viene inserita in un array o in una raccolta?

Array

Se si dispone di una matrice di oggetti, è ansible chiamare Arrays.toString() per produrre una semplice rappresentazione dei contenuti dell’array. Ad esempio, considera questo array di oggetti Person :

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

Nota: questa è una chiamata a un metodo statico chiamato toString() nella class Array, che è diverso da ciò che abbiamo discusso sopra.

Se si dispone di un array multidimensionale , è ansible utilizzare Arrays.deepToString() per ottenere lo stesso tipo di output.

collezioni

La maggior parte delle collezioni produrrà un output piuttosto basato sulla chiamata di .toString() su ogni elemento.

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

Quindi devi solo assicurarti che i tuoi elementi di lista definiscano un bel toString() come discusso sopra.

Penso che apache fornisca una migliore class util che fornisce una funzione per ottenere la stringa

 ReflectionToStringBuilder.toString(object) 

Ogni class in java ha il metodo toString() in esso di default, che viene chiamato da System.out.println() se passi qualche object di una class. Quando si tenta di stampare l’object di una class, il metodo System.out.println() chiamerà toString() della class che restituisce il codice hash className @ di tale object.

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

È ansible sovrascrivere il metodo toString di una class per ottenere output diversi. Vedi questo esempio

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

In Eclipse, vai alla class, fai clic con il tasto destro del mouse-> fonte-> Genera toString() ;

Sostituirà il metodo toString() e stamperà l’object di quella class.

Di default, ogni object in Java ha il metodo toString() che emette ObjectType @ HashCode.

Se si desiderano informazioni più significative, è necessario sovrascrivere il metodo toString() nella class.

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

Ora quando stampi l’object persona usando System.out.prtinln(personObj); stamperà il nome della persona anziché il nome della class e l’hashcode.

Nel secondo caso, quando si tenta di stampare la matrice, viene stampato [Lcom.foo.Person;@28a418fc il tipo di matrice e il codice hash.


Se si desidera stampare i nomi delle persone, ci sono molti modi.

Potresti scrivere la tua funzione che itera su ogni persona e stampa

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

Puoi stamparlo usando Arrays.toString (). Questo sembra il più semplice per me.

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

Potresti stamparlo java 8 way (usando stream e riferimento al metodo).

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

Potrebbero esserci anche altri modi. Spero che questo ti aiuti. 🙂

Se si stampa direttamente qualsiasi object di Person, verrà [email protected] al Codice.

nel tuo caso viene stampato [email protected] . Dove Person è una class a cui appartiene l’object e 2f92e0f4 è hashCode dell’object.

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

Ora se provi a utilizzare l’object di Person , verrà stampato il nome

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

In intellij puoi generare automaticamente il metodo toString premendo alt + inset e quindi selezionando toString () ecco un out out per una class di test:

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

Come puoi vedere, genera una stringa concatenando, diversi attributi della class, per le primitive stamperà i loro valori e per i tipi di riferimento userà il loro tipo di class (in questo caso il metodo stringa di Test2).

Se si osserva la class Object (class Parent di tutte le classi in Java), l’implementazione del metodo toString () è

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

ogni volta che si stampa qualsiasi object in Java, toString () sarà chiamato. Ora tocca a te se si esegue l’override di toString (), quindi il metodo chiamerà un’altra chiamata al metodo di class Object.

 Arrays.deepToString(arrayOfObject) 

Sopra la funzione stampa matrice di oggetti di primitive diverse.

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