Come posso stampare il mio oggetto Java senza ottenere "SomeType @ 2f92e0f4"?
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 Person
oggetti:
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
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 Object
classe (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@2f92e0f4
può quindi essere spiegato come:
com.foo.MyType
- il nome della classe, ovvero la classe èMyType
nel pacchettocom.foo
.@
- unisce la stringa insieme2f92e0f4
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.String
significa:
[
- un array monodimensionale (al contrario di[[
o[[[
ecc.)L
- l'array contiene una classe o un'interfacciajava.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 Person
classe 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:
@ToString
annotazione dal progetto Lombok
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 Person
oggetti:
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.
Penso che apache fornisca una classe util migliore che fornisce una funzione per ottenere la stringa
ReflectionToStringBuilder.toString(object)
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);
}
}
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.
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);
}
}
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).
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;@28a418fc
il 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. :)
Se stampi direttamente qualsiasi oggetto di persona sarà ClassName@HashCode
il codice.
nel tuo caso com.foo.Person@2f92e0f4
viene 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());
}
}
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.
Sono riuscito a farlo usando Jackson
nella 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 GSON
anche provare . Dovrebbe essere qualcosa del genere:
Gson gson = new Gson();
System.out.println(gson.toJson(objectYouWantToPrint).toString());