Wie drucke ich mein Java-Objekt, ohne "SomeType @ 2f92e0f4" zu erhalten?
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 Person
Objekten 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
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 Object
Klasse 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@2f92e0f4
kann daher erklärt werden als:
com.foo.MyType
- Der Name der Klasse, dh die Klasse befindet sichMyType
im Paketcom.foo
.@
- verbindet die Zeichenfolge miteinander2f92e0f4
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.String
bedeutet:
[
- ein eindimensionales Array (im Gegensatz zu[[
oder[[[
usw.)L
- Das Array enthält eine Klasse oder Schnittstellejava.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 Person
Klasse 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:
@ToString
Anmerkung aus dem Projekt Lombok
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 Person
Objekten:
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.
Ich denke, Apache bietet eine bessere util-Klasse, die eine Funktion zum Abrufen des Strings bietet
ReflectionToStringBuilder.toString(object)
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);
}
}
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.
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);
}
}
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).
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;@28a418fc
der 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. :) :)
Wenn Sie direkt ein Objekt der Person drucken, wird ClassName@HashCode
es zum Code.
in Ihrem Fall com.foo.Person@2f92e0f4
wird gedruckt. Wo Person
ist eine Klasse, zu der das Objekt gehört, und 2f92e0f4
ist 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());
}
}
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.
Ich habe es geschafft, dies mit Jackson
Spring 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 GSON
auch versuchen . Sollte so etwas sein:
Gson gson = new Gson();
System.out.println(gson.toJson(objectYouWantToPrint).toString());