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

300

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.

Podobnie stało się, gdy próbowałem wydrukować tablicę Personobiektów:

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

Mam wynik: [Lcom.foo.Person;@28a418fc

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

Uwaga : ma to na celu kanoniczne pytania i odpowiedzi na ten temat.

Duncan Jones
źródło
1
Możesz użyć biblioteki GSON do konwersji obiektu na Json i odwrotnie. Bardzo przydatne do debugowania.
Ashish Rawat

Odpowiedzi:

403

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 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 wyjaśnić jako:

  • com.foo.MyType - nazwa klasy, tzn. klasa znajduje się MyTypew paczce com.foo.
  • @ - łączy ciąg razem
  • 2f92e0f4 kod skrótu obiektu.

Nazwy klas tablic wyglądają nieco inaczej, co zostało dobrze wyjaśnione w Javadocs dla Class.getName(). Na przykład [Ljava.lang.Stringoznacza:

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

Dostosowywanie danych wyjściowych

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 wydrukujemy a Person, zobaczymy raczej ich nazwę com.foo.Person@12345678.

Pamiętaj, że toString()jest to tylko jeden sposób konwersji obiektu na ciąg. Zazwyczaj dane wyjściowe powinny w pełni opisywać obiekt w jasny i zwięzły sposób. Lepszym 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ę przydatny kawałek danych do debugowania / testowania.

Jeśli chcesz skupić się tylko na jednym aspekcie swojego obiektu lub zastosować wiele jazzy formatowania, lepiej zamiast tego zdefiniować oddzielną metodę, np String toElegantReport() {...}.


Automatyczne generowanie wyniku

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

Kilka popularnych bibliotek Java również oferuje tę funkcję. Niektóre przykłady obejmują:


Drukowanie grup obiektów

Więc stworzyłeś fajny 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()aby uzyskać 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ływanej toString()w klasie Arrays, która różni się od omawianej powyżej.

Jeśli masz tablicę wielowymiarową , możesz użyć Arrays.deepToString()tej samej wartości wyjściowej.

Kolekcje

Większość kolekcji będzie generować niezłe wyniki oparte na wywołaniu .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 tylko upewnić się, że elementy listy definiują ładne, toString()jak omówiono powyżej.

Duncan Jones
źródło
return String.format( getClass().getSimpleName() + "[ name=%s ]", name);i naprawdę zamiast nametego powinien używać gettera getName()(ale gettery zostały pominięte w klasie Person ...), ale jeśli użyty został getter ...return String.format( getClass().getSimpleName() + "[ name=%s ]", getName());
CrandellWS
jeśli mam dwie klasy w pliku java, to jak stworzyć obiekt klasy, która nie jest publiczna A.java klasa publiczna A {} klasa B {} ------ C.java klasa publiczna C {A a = nowa A ( ); }
yatinbc 10.10.16
Zauważ, że istnieją przeciążone wersje, Arrays.toString()więc możesz używać go również do tablic prymitywów ( int[], double[]). Arrays.deepToString()Ładnie obsługuje również wielowymiarowe tablice prymitywów.
Ole VV,
1
@ MasterJoe2 Nie jestem pewien, może myśleli, że będzie wyglądać brzydko, próbując zakodować wartości ujemne w ciągu?
Duncan Jones
55

Myślę, że apache zapewnia lepszą klasę wykorzystania, która zapewnia funkcję pobierania łańcucha

ReflectionToStringBuilder.toString(object)
Rohith K.
źródło
5
Ma to tę zaletę, że nie wymaga edycji klasy, co czasem jest niemożliwe. Jak mogę jednak rekurencyjnie drukować zagnieżdżone obiekty?
lukas84
34

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

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

Możesz 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);
    }
}
Pankaj Manali
źródło
3
Jest to dobrze postawiona i krótka odpowiedź, ale w celu wyjaśnienia, dlaczego OP otrzymuje [Lcom.foo.Person;@28a418fcjako wynik: to także wynik toString()metody, ale tej, która jest zaimplementowana w klasie generowanej w czasie wykonywania dla typu Person[], a nie Person(patrz stackoverflow.com/a/8546532/1542343 ).
gvlasov
To wyjście oznacza pakiet.Klasa@Kod skrótu. Domyślna metoda toString () ma typ zwracany jak. return Object.hasCode () lub podobna instrukcja return, która zwraca hashcode w postaci szesnastkowej wraz z nazwą klasy.
Pankaj Manali,
14

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

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

ketankk
źródło
10

Wolę używać funkcji narzędzia, która używa GSON do przekształcenia obiektu Java w postać szeregową w ciąg 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);
    }
}
Agam
źródło
Powinno być return Gson.toJson(object);, w przeciwnym razie działa idealnie.
Nakrule
To tylko to.
Agam
5

W intellij możesz automatycznie wygenerować metodę toString, naciskając alt + wstawkę, a następnie wybierając toString () tutaj jest 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 ciąg poprzez połączenie 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).

Mr.Q
źródło
4

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

Jeśli chcesz uzyskać więcej przydatnych 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, wydrukuje nazwisko osoby zamiast nazwy klasy i kodu skrótu.

W drugim przypadku, gdy próbujesz wydrukować tablicę, wypisuje [Lcom.foo.Person;@28a418fcona typ tablicy i 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ć java 8 sposób (używając strumieni i referencji metod).

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

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

i 911
źródło
3

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

w twoim przypadku com.foo.Person@2f92e0f4jest drukowane. Gdzie Personjest klasa, 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 Person, wydrukuje nazwę

Class Test
 {
  public static void main(String... args){
    Person obj = new Person("YourName");
    System.out.println(obj.toString());
  }
}
Vikrant Kashyap
źródło
2

Jeśli spojrzysz na klasę Object (klasa macierzysta wszystkich klas w Javie), implementacja metody toString () jest

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

za każdym razem, gdy drukujesz dowolny obiekt w Javie, wywoływana jest funkcja toString (). Teraz to od Ciebie zależy, czy przesłonisz metodę toString (), a następnie twoja metoda wywoła inne wywołanie metody klasy Object.

Yasir Shabbir Choudhary
źródło