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

Mar 19 2015

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.

Antworten

422 DuncanJones Mar 19 2015 at 15:59

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 Aufrufen 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 eine Menge jazziger Formatierungen hinzufügen 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.

61 RohithK Apr 15 2015 at 20:31

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

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

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);
    }
}
16 ketankk Apr 21 2016 at 20:45

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.

12 Agam Oct 09 2018 at 19:18

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);
    }
}
6 Mr.Q Jul 28 2016 at 13:00

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).

6 adn.911 Dec 02 2017 at 23:23

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. :) :)

4 VikrantKashyap May 06 2016 at 18:22

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());
  }
}
3 YasirShabbirChoudhary Mar 27 2017 at 13:21

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.

user9869932 Nov 06 2020 at 00:34

Ich habe es geschafft, dies mit JacksonSpring 5 zu erledigen . Je nach Objekt funktioniert Jackson möglicherweise nicht in allen Fällen.

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("-------------------------------------------------------------------")

Die Ausgabe wäre so etwas wie

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

Weitere Beispiele finden Sie Jackson hier

Sie können es GSONauch versuchen . Sollte so etwas sein:

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