Jak wydrukować obiekt Java bez otrzymywania komunikatu „SomeType @ 2f92e0f4”?

Mar 19 2015

Mam klasę zdefiniowaną w następujący sposób:

public class Person {
  private String name;

  // constructor and getter/setter omitted
}

Próbowałem wydrukować instancję mojej klasy:

System.out.println(myPerson);

ale mam następujący wynik: com.foo.Person@2f92e0f4.

Podobna rzecz wydarzyła się, gdy próbowałem wydrukować tablicę Personobiektów:

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

Mam wyjście: [Lcom.foo.Person;@28a418fc

Co oznacza ten wynik? Jak zmienić to wyjście, aby zawierało imię i nazwisko mojej osoby? Jak mogę wydrukować kolekcje moich obiektów?

Uwaga : to ma charakter kanoniczny pytań i odpowiedzi na ten temat.

Odpowiedzi

422 DuncanJones Mar 19 2015 at 15:59

tło

Wszystkie obiekty Java mają toString()metodę, która jest wywoływana podczas próby wydrukowania obiektu.

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

Ta metoda jest zdefiniowana w Objectklasie (nadklasie wszystkich obiektów Java). Object.toString()Metoda zwraca dość brzydki patrząc ciąg, składający się z nazwą klasy, a @symbolem i hashcode obiektu w systemie szesnastkowym. Kod do tego wygląda następująco:

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

Wynik taki com.foo.MyType@2f92e0f4można zatem wytłumaczyć jako:

  • com.foo.MyType - nazwa klasy, czyli klasa znajduje się MyTypew pakiecie com.foo.
  • @ - łączy ze sobą sznurek
  • 2f92e0f4 kod skrótu obiektu.

Nazwy klas tablic wyglądają trochę inaczej, co jest dobrze wyjaśnione w Javadocach dla Class.getName(). Na przykład [Ljava.lang.Stringoznacza:

  • [- tablica jednowymiarowa (w przeciwieństwie do [[lub [[[itp.)
  • L - tablica zawiera klasę lub interfejs
  • java.lang.String - rodzaj obiektów w tablicy

Dostosowywanie wyjścia

Aby wydrukować coś innego, kiedy zadzwonić System.out.println(myObject), należy zastąpić ten toString()sposób w swojej własnej klasie. Oto prosty przykład:

public class Person {

  private String name;
  
  // constructors and other methods omitted
  
  @Override
  public String toString() {
    return name;
  }
}

Teraz, jeśli drukujemy a Person, widzimy raczej ich nazwę niż com.foo.Person@12345678.

Należy pamiętać, że toString()jest to tylko jeden ze sposobów konwersji obiektu na łańcuch. Zwykle te dane wyjściowe powinny w pełni opisywać twój obiekt w jasny i zwięzły sposób. Lepszym rozwiązaniem toString()dla naszej Personklasy może być:

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

Który wydrukowałby np Person[name=Henry]. To naprawdę przydatna część danych do debugowania / testowania.

Jeśli chcesz skupić się tylko na jednym aspekcie obiektu lub zawrzeć dużo jazzy formatowania, lepiej zdefiniować oddzielną metodę, np String toElegantReport() {...}.


Automatyczne generowanie wyniku

Wiele IDE oferuje obsługę automatycznego generowania toString()metody na podstawie pól w klasie. Na przykład zobacz dokumentację dotyczącą Eclipse i IntelliJ .

Kilka popularnych bibliotek Java oferuje również tę funkcję. Oto kilka przykładów:


Drukowanie grup obiektów

Więc stworzyłeś miły toString()dla swojej klasy. Co się stanie, jeśli ta klasa zostanie umieszczona w tablicy lub kolekcji?

Tablice

Jeśli masz tablicę obiektów, możesz wywołać Arrays.toString()prostą reprezentację zawartości tablicy. Weźmy na przykład tę tablicę Personobiektów:

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

// Prints: [Fred, Mike]

Uwaga: jest to wywołanie metody statycznej wywołanej toString()w klasie Arrays, która różni się od tego, o czym rozmawialiśmy powyżej.

Jeśli masz tablicę wielowymiarową , możesz użyć jej Arrays.deepToString()do uzyskania tego samego rodzaju wyników.

Kolekcje

Większość kolekcji da ładny wynik w oparciu o wywołanie .toString()każdego elementu.

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

// Prints [Alice, Bob]

Musisz więc tylko upewnić się, że elementy listy definiują ładne, toString()jak omówiono powyżej.

61 RohithK Apr 15 2015 at 20:31

Myślę, że apache zapewnia lepszą klasę użytkową, która zapewnia funkcję pobierania ciągu

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

Każda klasa w Javie ma toString()domyślnie metodę, która jest wywoływana, jeśli przekażesz jakiś obiekt tej klasy do System.out.println(). Domyślnie to wywołanie zwraca nazwę klasy @ hashcode tego obiektu.

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

Można przesłonić metodę toString klasy, aby uzyskać inne dane wyjściowe. Zobacz ten przykład

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

W Eclipse, przejdź do swojej klasy, kliknij prawym przyciskiem myszy-> źródło-> Generuj toString();

Zastąpi toString()metodę i wydrukuje obiekt tej klasy.

12 Agam Oct 09 2018 at 19:18

Wolę używać funkcji narzędzia, która używa GSON do deserializacji obiektu Java do łańcucha 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);
    }
}
6 Mr.Q Jul 28 2016 at 13:00

W intellij możesz automatycznie wygenerować metodę toString, naciskając alt + inset, a następnie wybierając toString (), oto wyjście dla klasy testowej:

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

Jak widać, generuje String przez konkatenację kilku atrybutów klasy, dla prymitywów wypisze ich wartości, a dla typów referencyjnych użyje ich typu klasy (w tym przypadku do metody łańcuchowej Test2).

6 adn.911 Dec 02 2017 at 23:23

Domyślnie każdy obiekt w Javie ma toString()metodę, która wyprowadza ObjectType @ HashCode.

Jeśli chcesz uzyskać więcej znaczących informacji, musisz zastąpić toString()metodę w swojej klasie.

public class Person {
  private String name;

  // constructor and getter/setter omitted

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

Teraz, gdy drukujesz obiekt osoby, używając System.out.prtinln(personObj);go, wypisze imię osoby zamiast nazwy klasy i kodu skrótu.

W drugim przypadku, gdy próbujesz wydrukować tablicę, [Lcom.foo.Person;@28a418fcwyświetla typ tablicy i jej kod skrótu.


Jeśli chcesz wydrukować nazwiska osób, istnieje wiele sposobów.

Możesz napisać własną funkcję, która iteruje każdą osobę i drukuje

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

Możesz go wydrukować za pomocą Arrays.toString (). Wydaje mi się to najprostsze.

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

Możesz wydrukować go w sposób java 8 (używając strumieni i odniesienia do metody).

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

Mogą być też inne sposoby. Mam nadzieję że to pomoże. :)

4 VikrantKashyap May 06 2016 at 18:22

Jeśli bezpośrednio wydrukujesz obiekt osoby, będzie ClassName@HashCodeto zgodne z Kodeksem.

w twoim przypadku com.foo.Person@2f92e0f4jest drukowany. Where Personjest klasą, do której należy obiekt i 2f92e0f4jest hashCode obiektu.

public class Person {
  private String name;

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

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

Teraz, jeśli spróbujesz użyć obiektu, Personto wypisze nazwę

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

Jeśli spojrzymy na klasę Object (klasa nadrzędna wszystkich klas w Javie), implementacja metody toString () to

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

za każdym razem, gdy drukujesz dowolny obiekt w Javie, zostanie wywołana toString (). Teraz to od Ciebie zależy, czy zastąpisz toString (), a Twoja metoda wywoła inne wywołanie metody klasy Object.

user9869932 Nov 06 2020 at 00:34

Udało mi się to zrobić, używając Jacksonwiosny 5. W zależności od obiektu Jackson może nie działać we wszystkich przypadkach.

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

wynik byłby podobny

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

Więcej przykładów Jackson tutaj

Możesz GSONteż spróbować . Powinno wyglądać mniej więcej tak:

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