Comment imprimer mon objet Java sans obtenir «SomeType @ 2f92e0f4»?
J'ai une classe définie comme suit:
public class Person {
private String name;
// constructor and getter/setter omitted
}
J'ai essayé d'imprimer une instance de ma classe:
System.out.println(myPerson);
mais je suis la sortie suivante: com.foo.Person@2f92e0f4
.
Une chose similaire s'est produite lorsque j'ai essayé d'imprimer un tableau d' Person
objets:
Person[] people = //...
System.out.println(people);
J'ai la sortie: [Lcom.foo.Person;@28a418fc
Que signifie cette sortie? Comment modifier cette sortie pour qu'elle contienne le nom de ma personne? Et comment imprimer des collections de mes objets?
Remarque : ceci est conçu comme une question-réponse canonique sur ce sujet.
Réponses
Contexte
Tous les objets Java ont une toString()
méthode, qui est appelée lorsque vous essayez d'imprimer l'objet.
System.out.println(myObject); // invokes myObject.toString()
Cette méthode est définie dans la Object
classe (la superclasse de tous les objets Java). La Object.toString()
méthode renvoie une chaîne assez moche, composée du nom de la classe, d'un @
symbole et du hashcode de l'objet en hexadécimal. Le code pour cela ressemble à:
// Code of Object.toString()
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
Un résultat tel que com.foo.MyType@2f92e0f4
peut donc s'expliquer par:
com.foo.MyType
- le nom de la classe, c'est-à-dire que la classe estMyType
dans le packagecom.foo
.@
- joint la chaîne ensemble2f92e0f4
le hashcode de l'objet.
Le nom des classes de tableaux est un peu différent, ce qui est bien expliqué dans les Javadocs pour Class.getName()
. Par exemple, cela [Ljava.lang.String
signifie:
[
- un tableau unidimensionnel (par opposition à[[
ou[[[
etc.)L
- le tableau contient une classe ou une interfacejava.lang.String
- le type d'objets dans le tableau
Personnalisation de la sortie
Pour imprimer quelque chose de différent lorsque vous appelez System.out.println(myObject)
, vous devez remplacer la toString()
méthode dans votre propre classe. Voici un exemple simple:
public class Person {
private String name;
// constructors and other methods omitted
@Override
public String toString() {
return name;
}
}
Maintenant, si nous imprimons un Person
, nous voyons leur nom plutôt que com.foo.Person@12345678
.
Gardez à l'esprit que ce toString()
n'est qu'une façon pour un objet d'être converti en chaîne. En règle générale, cette sortie doit décrire complètement votre objet de manière claire et concise. Un meilleur toString()
pour notre Person
classe pourrait être:
@Override
public String toString() {
return getClass().getSimpleName() + "[name=" + name + "]";
}
Ce qui imprimerait, par exemple Person[name=Henry]
. C'est une donnée vraiment utile pour le débogage / test.
Si vous souhaitez vous concentrer sur un seul aspect de votre objet ou inclure beaucoup de mise en forme jazzy, vous feriez peut-être mieux de définir une méthode distincte à la place, par exemple String toElegantReport() {...}
.
Génération automatique de la sortie
De nombreux IDE prennent en charge la génération automatique d'une toString()
méthode, en fonction des champs de la classe. Consultez la documentation pour Eclipse et IntelliJ , par exemple.
Plusieurs bibliothèques Java populaires offrent également cette fonctionnalité. Quelques exemples incluent:
@ToString
annotation du projet Lombok
Impression de groupes d'objets
Vous avez donc créé un joli toString()
pour votre classe. Que se passe-t-il si cette classe est placée dans un tableau ou une collection?
Tableaux
Si vous avez un tableau d'objets, vous pouvez appeler Arrays.toString()
pour produire une représentation simple du contenu du tableau. Par exemple, considérez ce tableau d' Person
objets:
Person[] people = { new Person("Fred"), new Person("Mike") };
System.out.println(Arrays.toString(people));
// Prints: [Fred, Mike]
Remarque: il s'agit d'un appel à une méthode statique appelée toString()
dans la classe Arrays, qui est différente de ce dont nous avons discuté ci-dessus.
Si vous avez un tableau multidimensionnel , vous pouvez utiliser Arrays.deepToString()
pour obtenir le même type de sortie.
Les collections
La plupart des collections produiront une jolie sortie basée sur l'appel .toString()
de chaque élément.
List<Person> people = new ArrayList<>();
people.add(new Person("Alice"));
people.add(new Person("Bob"));
System.out.println(people);
// Prints [Alice, Bob]
Il vous suffit donc de vous assurer que les éléments de votre liste définissent un joli toString()
comme indiqué ci-dessus.
Je pense qu'apache fournit une meilleure classe util qui fournit une fonction pour obtenir la chaîne
ReflectionToStringBuilder.toString(object)
Chaque classe en Java contient la toString()
méthode par défaut, qui est appelée si vous passez un objet de cette classe à System.out.println()
. Par défaut, cet appel renvoie le className @ hashcode de cet objet.
{
SomeClass sc = new SomeClass();
// Class @ followed by hashcode of object in Hexadecimal
System.out.println(sc);
}
Vous pouvez remplacer la méthode toString d'une classe pour obtenir une sortie différente. Voir cet exemple
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);
}
}
Dans Eclipse, allez dans votre classe, faites un clic droit-> source-> Générer toString()
;
Il remplacera la toString()
méthode et imprimera l'objet de cette classe.
Je préfère utiliser une fonction utilitaire qui utilise GSON pour désérialiser l'objet Java en chaîne 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);
}
}
Dans intellij, vous pouvez générer automatiquement la méthode toString en appuyant sur alt + inset, puis en sélectionnant toString (), voici une sortie pour une classe de 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 +
'}';
}
}
Comme vous pouvez le voir, il génère une chaîne en concaténant plusieurs attributs de la classe, pour les primitives, il affichera leurs valeurs et pour les types de référence, il utilisera leur type de classe (dans ce cas à la méthode de chaîne de Test2).
Par défaut, chaque objet en Java a la toString()
méthode qui génère le ObjectType @ HashCode.
Si vous voulez des informations plus significatives, vous devez remplacer la toString()
méthode dans votre classe.
public class Person {
private String name;
// constructor and getter/setter omitted
// overridding toString() to print name
public String toString(){
return name;
}
}
Désormais, lorsque vous imprimez l'objet personne en l'utilisant, System.out.prtinln(personObj);
il affichera le nom de la personne au lieu du nom de classe et du hashcode.
Dans votre deuxième cas, lorsque vous essayez d'imprimer le tableau, il imprime [Lcom.foo.Person;@28a418fc
le type Array et son hashcode.
Si vous souhaitez imprimer les noms des personnes, il existe de nombreuses façons.
Vous pouvez écrire votre propre fonction qui itère chaque personne et imprime
void printPersonArray(Person[] persons){
for(Person person: persons){
System.out.println(person);
}
}
Vous pouvez l'imprimer en utilisant Arrays.toString (). Cela me semble le plus simple.
System.out.println(Arrays.toString(persons));
System.out.println(Arrays.deepToString(persons)); // for nested arrays
Vous pouvez l'imprimer de la manière java 8 (en utilisant des flux et une référence de méthode).
Arrays.stream(persons).forEach(System.out::println);
Il pourrait également y avoir d'autres moyens. J'espère que cela t'aides. :)
Si vous imprimez directement un objet de Person, il le sera ClassName@HashCode
au code.
dans votre cas com.foo.Person@2f92e0f4
est imprimé. Où Person
est une classe à laquelle appartient l'objet et 2f92e0f4
est le hashCode de l'objet.
public class Person {
private String name;
public Person(String name){
this.name = name;
}
// getter/setter omitted
@override
public String toString(){
return name;
}
}
Maintenant, si vous essayez d'utiliser l'objet de, Person
il imprimera le nom
Class Test
{
public static void main(String... args){
Person obj = new Person("YourName");
System.out.println(obj.toString());
}
}
Si vous regardez la classe Object (classe parente de toutes les classes en Java), l'implémentation de la méthode toString () est
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
chaque fois que vous imprimez un objet en Java, toString () sera appelé. Maintenant, c'est à vous de décider si vous remplacez toString (), votre méthode appellera un autre appel de méthode de classe Object.
J'ai réussi à le faire en utilisant Jackson
au printemps 5. Selon l'objet, Jackson pourrait ne pas fonctionner dans tous les cas.
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("-------------------------------------------------------------------")
la sortie serait quelque chose comme
-------------------------------------------------------------------
{
"id" : 1,
"internalStaffId" : "1",
"staffCms" : 1,
"createdAt" : "1",
"updatedAt" : "1",
"staffTypeChange" : null,
"staffOccupationStatus" : null,
"staffNote" : null
}
-------------------------------------------------------------------
Plus d'exemples d'utilisation Jackson
ici
Vous pouvez GSON
aussi essayer . Devrait être quelque chose comme ça:
Gson gson = new Gson();
System.out.println(gson.toJson(objectYouWantToPrint).toString());