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


301

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 è accaduta quando ho provato a stampare una matrice 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 stampo le raccolte dei miei oggetti?

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


1
È possibile utilizzare la libreria GSON per convertire l'oggetto in json e viceversa. Molto utile per il debug.
Ashish Rawat,

Risposte:


403

sfondo

Tutti gli oggetti Java hanno un toString()metodo, che viene invocato 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 piuttosto brutto, composta dal nome della classe, un @simbolo e l' hashcode dell'oggetto in esadecimale. Il codice per questo sembra:

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

Un risultato come quello 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
  • 2f92e0f4 l'hashcode dell'oggetto.

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

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

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 piuttosto che com.foo.Person@12345678.

Tieni presente che 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. Un migliore toString()per la nostra Personclasse potrebbe essere:

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

Che verrebbe stampato, ad es Person[name=Henry]. È un dato davvero utile per il debugging / testing.

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


Generazione automatica dell'uscita

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

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


Stampa di gruppi di oggetti

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

Array

Se si dispone di una matrice di oggetti, è possibile chiamare Arrays.toString()per produrre una semplice rappresentazione del contenuto della matrice. 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 di cui abbiamo discusso in precedenza.

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

collezioni

La maggior parte delle raccolte produrrà un output piuttosto basato sulla chiamata .toString()su 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 aspetto gradevole toString()come discusso sopra.


return String.format( getClass().getSimpleName() + "[ name=%s ]", name);e in realtà invece namedovrebbe usare il getter getName()(ma i getter sono stati omessi nella classe Person ...) ma se fosse usato un getter ...return String.format( getClass().getSimpleName() + "[ name=%s ]", getName());
CrandellWS,

se ho due classi nel file java, allora come creare un oggetto di classe che non sia pubblico A.java classe pubblica A {} classe B {} ------ C.java classe pubblica C {A a = new A ( ); }
yatinbc,

Nota che ci sono versioni sovraccaricate di Arrays.toString()così puoi usarlo anche per matrici di primitive ( int[], double[]). Arrays.deepToString()Gestisce bene anche array multidimensionali di primitivi.
Ole VV,

1
@ MasterJoe2 Non sono sicuro, forse hanno pensato che sarebbe stato brutto provare a codificare valori negativi nella stringa?
Duncan Jones,

55

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

ReflectionToStringBuilder.toString(object)

5
Ciò ha il vantaggio di non richiedere la modifica della classe, cosa che a volte non è possibile. Tuttavia, come posso stampare in modo ricorsivo anche oggetti nidificati?
lukas84,

35

Ogni classe in Java ha il toString()metodo in esso predefinito, che viene chiamato se si passa qualche oggetto di quella classe a System.out.println(). Per impostazione predefinita, questa chiamata restituisce className @ hashcode 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);
    }
}

3
Questa è una risposta ben fatta e breve, ma per chiarire perché OP sta ottenendo [Lcom.foo.Person;@28a418fccome output: anche questo è l'output del toString()metodo, ma di quello implementato nella classe che viene generato in fase di esecuzione per il tipo Person[], non Person(vedi stackoverflow.com/a/8546532/1542343 ).
gvlasov,

Questo output significa package.Class@Hashcode. Il metodo predefinito toString () ha tipo restituito come. return Object.hasCode () o un'istruzione return simile che restituisce hashcode in forma esadecimale insieme al nome della classe.
Pankaj Manali,

14

In Eclipse, vai alla tua classe, fai clic destro-> sorgente-> Genera toString();

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


10

Preferisco utilizzare una funzione di utilità che utilizza GSON per deserializzare l'oggetto Java nella 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);
    }
}

Dovrebbe essere return Gson.toJson(object);, altrimenti funzionerà perfettamente.
Nakrule,

È solo quello.
Agam,

5

In intellij è possibile generare automaticamente il metodo toString premendo alt + inset e quindi selezionando toString () ecco un risultato 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 userà il loro tipo di classe (in questo caso per stringare il metodo di Test2).


4

Per impostazione predefinita, ogni oggetto in Java ha il toString()metodo che genera l'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 che lo utilizza System.out.prtinln(personObj);, verrà stampato il nome della persona anziché il nome classe e l'hashcode.

Nel tuo secondo caso, quando stai provando a stampare l'array, stampa [Lcom.foo.Person;@28a418fcil tipo di array ed è hashcode.


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

È possibile stamparlo utilizzando 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 modo java 8 (utilizzando flussi e riferimento al metodo).

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

Potrebbero esserci anche altri modi. Spero che questo ti aiuti. :)


3

Se si stampa direttamente qualsiasi oggetto di persona sarà ClassName@HashCodeal 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 si tenta di 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());
  }
}

2

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.