Come posso stampare il mio oggetto Java senza ottenere "SomeType @ 2f92e0f4"?

Mar 19 2015

Ho una classe definita come segue:

public class Person {
  private String name;

  // constructor and getter/setter omitted
}

Ho provato a stampare un'istanza della mia classe:

System.out.println(myPerson);

ma ho ottenuto il seguente risultato: com.foo.Person@2f92e0f4.

Una cosa simile è successa quando ho provato a stampare un array di Personoggetti:

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

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

Cosa significa questo output? Come posso modificare questo output in modo che contenga il nome della mia persona? E come si stampano le raccolte dei miei oggetti?

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

Risposte

422 DuncanJones Mar 19 2015 at 15:59

sfondo

Tutti gli oggetti Java hanno un toString()metodo, che viene richiamato quando si tenta di stampare l'oggetto.

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

Questo metodo è definito nella Objectclasse (la superclasse di tutti gli oggetti Java). Il Object.toString()metodo restituisce una stringa dall'aspetto abbastanza brutto, composta dal nome della classe, un @simbolo e l' hashcode dell'oggetto in esadecimale. Il codice per questo assomiglia a:

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

Un risultato come com.foo.MyType@2f92e0f4può quindi essere spiegato come:

  • com.foo.MyType - il nome della classe, ovvero la classe è MyTypenel pacchetto com.foo.
  • @ - unisce la stringa insieme
  • 2f92e0f4 il codice hash dell'oggetto.

Il nome delle classi di array ha un aspetto leggermente diverso, il che è spiegato bene nei Javadoc per Class.getName(). Ad esempio, [Ljava.lang.Stringsignifica:

  • [- un array monodimensionale (al contrario di [[o [[[ecc.)
  • L - l'array contiene una classe o un'interfaccia
  • java.lang.String - il tipo di oggetti nell'array

Personalizzazione dell'output

Per stampare qualcosa di diverso quando chiami System.out.println(myObject), devi sovrascrivere il toString()metodo nella tua classe. Ecco un semplice esempio:

public class Person {

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

Ora se stampiamo un Person, vediamo il loro nome invece di com.foo.Person@12345678.

Tieni presente che questo toString()è solo un modo per convertire un oggetto in una stringa. In genere questo output dovrebbe descrivere completamente il tuo oggetto in modo chiaro e conciso. Una soluzione migliore toString()per la nostra Personclasse potrebbe essere:

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

Che sarebbe stampare, ad esempio, Person[name=Henry]. Questo è un pezzo di dati davvero utile per il debug / test.

Se vuoi concentrarti su un solo aspetto del tuo oggetto o includere molta formattazione jazz, potresti essere meglio definire invece un metodo separato, ad es String toElegantReport() {...}.


Generazione automatica dell'output

Molti IDE offrono supporto per la generazione automatica di un toString()metodo, in base ai campi nella classe. Vedere la documentazione per Eclipse e IntelliJ , ad esempio.

Diverse librerie Java popolari offrono anche questa funzione. Alcuni esempi includono:


Stampa di gruppi di oggetti

Quindi hai creato un simpatico toString()per la tua classe. Cosa succede se quella classe viene inserita in un array o in una raccolta?

Arrays

Se hai un array di oggetti, puoi chiamare Arrays.toString()per produrre una semplice rappresentazione del contenuto dell'array. Ad esempio, considera questo array di Personoggetti:

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 classe Arrays, che è diverso da quello che abbiamo discusso sopra.

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

Collezioni

La maggior parte delle raccolte produrrà un bel risultato basato sulla chiamata di .toString()ogni elemento.

List<Person> 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 gli elementi della tua lista definiscano un bello toString()come discusso sopra.

61 RohithK Apr 15 2015 at 20:31

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

ReflectionToStringBuilder.toString(object)
37 PankajManali Mar 19 2015 at 17:04

Ogni classe in Java ha il toString()metodo per impostazione predefinita, che viene chiamato se si passa un oggetto di quella classe a System.out.println(). Per impostazione predefinita, questa chiamata restituisce il codice hash className @ di quell'oggetto.

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

È possibile sovrascrivere il metodo toString di una classe per ottenere un output diverso. 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);
    }
}
16 ketankk Apr 21 2016 at 20:45

In Eclipse, vai alla tua classe, fai clic con il pulsante destro del mouse-> sorgente-> Genera toString();

Sostituirà il toString()metodo e stamperà l'oggetto di quella classe.

12 Agam Oct 09 2018 at 19:18

Preferisco utilizzare una funzione di utilità che utilizza GSON per de-serializzare l'oggetto Java in una stringa 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);
    }
}
6 Mr.Q Jul 28 2016 at 13:00

In intellij puoi generare automaticamente il metodo toString premendo alt + inset e quindi selezionando toString () ecco un'uscita per una classe 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 classe, per le primitive stamperà i loro valori e per i tipi di riferimento utilizzerà il loro tipo di classe (in questo caso al metodo stringa di Test2).

6 adn.911 Dec 02 2017 at 23:23

Per impostazione predefinita, ogni oggetto in Java ha il toString()metodo che restituisce ObjectType @ HashCode.

Se desideri informazioni più significative, devi sovrascrivere il toString()metodo nella tua classe.

public class Person {
  private String name;

  // constructor and getter/setter omitted

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

Ora, quando si stampa l'oggetto persona usandolo System.out.prtinln(personObj);, verrà stampato il nome della persona invece del nome della classe e del codice hash.

Nel secondo caso, quando si tenta di stampare l'array, viene stampato [Lcom.foo.Person;@28a418fcil tipo di array e il suo codice hash.


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

Potresti scrivere la tua funzione che itera ogni persona e stampa

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

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

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

È possibile stamparlo in Java 8 way (utilizzando flussi e riferimento al metodo).

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

Potrebbero esserci anche altri modi. Spero che sia di aiuto. :)

4 VikrantKashyap May 06 2016 at 18:22

Se stampi direttamente qualsiasi oggetto di persona sarà ClassName@HashCodeil codice.

nel tuo caso com.foo.Person@2f92e0f4viene stampato. Where Personè una classe a cui appartiene l'oggetto ed 2f92e0f4è hashCode dell'oggetto.

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'oggetto di Person, verrà stampato il nome

Class Test
 {
  public static void main(String... args){
    Person obj = new Person("YourName");
    System.out.println(obj.toString());
  }
}
3 YasirShabbirChoudhary Mar 27 2017 at 13:21

Se guardi la classe Object (classe padre 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 un oggetto in Java, verrà chiamato toString (). Ora dipende da te se esegui l'override di toString (), il tuo metodo chiamerà un'altra chiamata al metodo della classe Object.

user9869932 Nov 06 2020 at 00:34

Sono riuscito a farlo usando Jacksonnella primavera 5. A seconda dell'oggetto Jackson potrebbe non funzionare in tutti i casi.

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

ObjectMapper mapper = new ObjectMapper();
Staff staff = createStaff();
// pretty print
String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(staff);
System.out.println("-------------------------------------------------------------------")
System.out.println(json);
System.out.println("-------------------------------------------------------------------")

l'output sarebbe qualcosa di simile

-------------------------------------------------------------------
{
  "id" : 1,
  "internalStaffId" : "1",
  "staffCms" : 1,
  "createdAt" : "1",
  "updatedAt" : "1",
  "staffTypeChange" : null,
  "staffOccupationStatus" : null,
  "staffNote" : null
}
-------------------------------------------------------------------

Altri esempi usando Jackson qui

Puoi GSONanche provare . Dovrebbe essere qualcosa del genere:

Gson gson = new Gson();
System.out.println(gson.toJson(objectYouWantToPrint).toString());