Wie drucke ich mein Java-Objekt, ohne "SomeType @ 2f92e0f4" zu erhalten?

300

Ich habe eine Klasse wie folgt definiert:

public class Person {
  private String name;

  // constructor and getter/setter omitted
}

Ich habe versucht, eine Instanz meiner Klasse zu drucken:

System.out.println(myPerson);

aber ich habe folgende ausgabe bekommen : com.foo.Person@2f92e0f4.

Ähnliches geschah, als ich versuchte, eine Reihe von PersonObjekten zu drucken :

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

Ich habe die Ausgabe bekommen: [Lcom.foo.Person;@28a418fc

Was bedeutet diese Ausgabe? Wie ändere ich diese Ausgabe so, dass sie den Namen meiner Person enthält? Und wie drucke ich Sammlungen meiner Objekte?

Hinweis : Dies ist als kanonische Frage und Antwort zu diesem Thema gedacht.

Duncan Jones
quelle
1
Sie können die GSON- Bibliothek verwenden, um Objekte in JSON zu konvertieren und umgekehrt. Sehr nützlich zum Debuggen.
Ashish Rawat

Antworten:

403

Hintergrund

Alle Java-Objekte verfügen über eine toString()Methode, die aufgerufen wird, wenn Sie versuchen, das Objekt zu drucken.

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

Diese Methode wird in der ObjectKlasse definiert (der Oberklasse aller Java-Objekte). Die Object.toString()Methode gibt eine ziemlich hässlich aussehende Zeichenfolge zurück, die aus dem Namen der Klasse, einem @Symbol und dem Hashcode des Objekts hexadezimal besteht. Der Code dafür sieht so aus:

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

Ein Ergebnis wie com.foo.MyType@2f92e0f4kann daher erklärt werden als:

  • com.foo.MyType - Der Name der Klasse, dh die Klasse befindet sich MyTypeim Paket com.foo.
  • @ - verbindet die Zeichenfolge miteinander
  • 2f92e0f4 der Hashcode des Objekts.

Der Name der Array-Klassen sieht etwas anders aus, was in den Javadocs für gut erklärt wird Class.getName(). Zum Beispiel [Ljava.lang.Stringbedeutet:

  • [- ein eindimensionales Array (im Gegensatz zu [[oder [[[usw.)
  • L - Das Array enthält eine Klasse oder Schnittstelle
  • java.lang.String - die Art der Objekte im Array

Anpassen der Ausgabe

Um beim Aufruf etwas anderes zu drucken System.out.println(myObject), müssen Sie die Methode in Ihrer eigenen Klasse überschreibentoString() . Hier ist ein einfaches Beispiel:

public class Person {

  private String name;

  // constructors and other methods omitted

  @Override
  public String toString() {
    return name;
  }
}

Wenn wir nun a drucken Person, sehen wir eher ihren Namen als com.foo.Person@12345678.

Beachten Sie, dass dies toString()nur eine Möglichkeit ist, ein Objekt in eine Zeichenfolge zu konvertieren. In der Regel sollte diese Ausgabe Ihr Objekt klar und präzise beschreiben. Ein besseres toString()für unsere PersonKlasse könnte sein:

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

Welches würde drucken, z Person[name=Henry]. Das sind wirklich nützliche Daten zum Debuggen / Testen.

Wenn Sie sich nur auf einen Aspekt Ihres Objekts konzentrieren oder viel jazzige Formatierung verwenden möchten, ist es möglicherweise besser, stattdessen eine separate Methode zu definieren, z String toElegantReport() {...}.


Ausgabe automatisch generieren

Viele IDEs bieten Unterstützung für die automatische Generierung einer toString()Methode basierend auf den Feldern in der Klasse. Siehe zum Beispiel Dokumente für Eclipse und IntelliJ .

Einige beliebte Java-Bibliotheken bieten diese Funktion ebenfalls an. Einige Beispiele sind:


Drucken von Objektgruppen

Sie haben also ein schönes toString()für Ihre Klasse erstellt. Was passiert, wenn diese Klasse in ein Array oder eine Sammlung eingefügt wird?

Arrays

Wenn Sie ein Array von Objekten haben, können Sie aufrufen Arrays.toString(), um eine einfache Darstellung des Inhalts des Arrays zu erstellen. Betrachten Sie beispielsweise dieses Array von PersonObjekten:

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

// Prints: [Fred, Mike]

Hinweis: Dies ist ein Aufruf einer statischen Methode, die toString()in der Arrays-Klasse aufgerufen wird und sich von der oben beschriebenen unterscheidet.

Wenn Sie ein mehrdimensionales Array haben , können Sie Arrays.deepToString()dieselbe Art von Ausgabe erzielen.

Sammlungen

Die meisten Sammlungen erzeugen eine hübsche Ausgabe, wenn .toString()jedes Element aufgerufen wird.

List<Person> people = new ArrayList<>();
people.add(new Person("Alice"));
people.add(new Person("Bob"));    
System.out.println(people);

// Prints [Alice, Bob]

Sie müssen also nur sicherstellen, dass Ihre Listenelemente ein schönes definieren, toString()wie oben beschrieben.

Duncan Jones
quelle
return String.format( getClass().getSimpleName() + "[ name=%s ]", name);und wirklich stattdessen namesollte der Getter verwendet werden getName()(aber Getter wurden in der Person-Klasse weggelassen ...), aber wenn ein Getter verwendet wurde ...return String.format( getClass().getSimpleName() + "[ name=%s ]", getName());
CrandellWS
Wenn ich zwei Klassen in der Java-Datei habe, wie erstelle ich ein Objekt der Klasse, das nicht öffentlich ist? A.java öffentliche Klasse A {} Klasse B {} ------ C.java öffentliche Klasse C {A a = new A ( ); }
Yatinbc
Beachten Sie, dass es überladene Versionen von gibt, Arrays.toString()sodass Sie sie auch für Arrays von Grundelementen verwenden können ( int[], double[]). Auch Arrays.deepToString()Griffe multidimensionalen Arrays von Primitiven schön.
Ole VV
1
@ MasterJoe2 Nicht sicher, vielleicht dachten sie, es würde hässlich aussehen, wenn sie versuchen, negative Werte in den String zu kodieren?
Duncan Jones
55

Ich denke, Apache bietet eine bessere util-Klasse, die eine Funktion zum Abrufen des Strings bietet

ReflectionToStringBuilder.toString(object)
Rohith K.
quelle
5
Dies hat den Vorteil, dass die Klasse nicht bearbeitet werden muss, was manchmal nicht möglich ist. Wie kann ich jedoch auch verschachtelte Objekte rekursiv drucken?
lukas84
35

Jede Klasse in Java enthält toString()standardmäßig die Methode, die aufgerufen wird, wenn Sie ein Objekt dieser Klasse an übergeben System.out.println(). Standardmäßig gibt dieser Aufruf den Klassennamen @ Hashcode dieses Objekts zurück.

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

Sie können die toString-Methode einer Klasse überschreiben, um eine andere Ausgabe zu erhalten. Siehe dieses Beispiel

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);
    }
}
Pankaj Manali
quelle
3
Dies ist eine gut formulierte und kurze Antwort, aber um zu verdeutlichen, warum OP [Lcom.foo.Person;@28a418fcals Ausgabe erhalten wird: Dies ist auch die Ausgabe der toString()Methode, aber derjenigen, die in der Klasse implementiert ist, die zur Laufzeit für den Typ generiert wird Person[], nicht Person(siehe stackoverflow.com/a/8546532/1542343 ).
Gvlasov
Diese Ausgabe bedeutet package.Class@Hashcode. Die Standardmethode toString () hat den Rückgabetyp like. return Object.hasCode () oder eine ähnliche return-Anweisung, die Hashcode in hexadezimaler Form zusammen mit dem Klassennamen zurückgibt.
Pankaj Manali
14

Gehen Sie in Eclipse zu Ihrer Klasse. Klicken Sie mit der rechten Maustaste auf> Quelle-> Generieren toString().

Es überschreibt die toString()Methode und druckt das Objekt dieser Klasse.

Ketankk
quelle
10

Ich bevorzuge die Verwendung einer Dienstprogrammfunktion, die GSON verwendet, um das Java-Objekt in eine JSON-Zeichenfolge zu de-serialisieren.

/**
 * 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);
    }
}
Agam
quelle
Es sollte sein return Gson.toJson(object);, sonst perfekt funktionieren.
Nakrule
Es ist nur das.
Agam
5

In Intellij können Sie die toString-Methode automatisch generieren, indem Sie Alt + Inset drücken und dann toString () auswählen. Hier ist eine Ausgabe für eine Testklasse:

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

Wie Sie sehen können, wird ein String generiert, indem mehrere Attribute der Klasse verkettet werden. Bei Grundelementen werden die Werte gedruckt, und bei Referenztypen wird der Klassentyp verwendet (in diesem Fall die String-Methode von Test2).

Mr.Q.
quelle
4

Standardmäßig verfügt jedes Objekt in Java über die toString()Methode, die den ObjectType @ HashCode ausgibt.

Wenn Sie aussagekräftigere Informationen wünschen, müssen Sie die toString()Methode in Ihrer Klasse überschreiben .

public class Person {
  private String name;

  // constructor and getter/setter omitted

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

Wenn Sie nun das Personenobjekt System.out.prtinln(personObj);damit drucken, wird der Name der Person anstelle des Klassennamens und des Hashcodes gedruckt.

In Ihrem zweiten Fall, wenn Sie versuchen, das Array zu drucken, wird [Lcom.foo.Person;@28a418fcder Array-Typ und sein Hashcode gedruckt.


Wenn Sie die Personennamen drucken möchten, gibt es viele Möglichkeiten.

Sie können Ihre eigene Funktion schreiben, die jede Person iteriert und druckt

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

Sie können es mit Arrays.toString () drucken. Das scheint mir am einfachsten zu sein.

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

Sie können es auf Java 8-Weise drucken (unter Verwendung von Streams und Methodenreferenzen).

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

Es könnte auch andere Wege geben. Hoffe das hilft. :) :)

adn.911
quelle
3

Wenn Sie direkt ein Objekt der Person drucken, wird ClassName@HashCodees zum Code.

in Ihrem Fall com.foo.Person@2f92e0f4wird gedruckt. Wo Personist eine Klasse, zu der das Objekt gehört, und 2f92e0f4ist der Hashcode des Objekts ?

public class Person {
  private String name;

  public Person(String name){
  this.name = name;
  }
  // getter/setter omitted

   @override
   public String toString(){
        return name;
   }
}

Wenn Sie nun versuchen, das Objekt von zu verwenden Person, wird der Name gedruckt

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

Wenn Sie sich die Object-Klasse (übergeordnete Klasse aller Klassen in Java) ansehen, lautet die Implementierung der toString () -Methode

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

Wenn Sie ein Objekt in Java drucken, wird toString () aufgerufen. Wenn Sie toString () überschreiben, liegt es nun an Ihnen, dass Ihre Methode einen anderen Methodenaufruf für die Objektklasse aufruft.

Yasir Shabbir Choudhary
quelle