Jak poprawnie zastąpić toString () w Javie?

87

Brzmi trochę głupio, ale potrzebuję pomocy w mojej toString()metodzie i jest to bardzo irytujące. Próbowałem wyszukać w Internecie, ponieważtoString jest ten, w którym coś schrzanił i „nie znajduję konstruktora Kida nr 2”, mimo że tam jest i nawet zrobiłbym coś innego i to nie działa. Ok, to było dużo, więc oto mój kod:

import java.util.*; 
   class Kid {  
      String name; 
      double height; 
      GregorianCalendar bDay; 

      public Kid () { 
         this.name = "HEAD";
         this.height = 1; 
         this.bDay = new GregorianCalendar(1111,1,1); 
      } 

      public Kid (String n, double h, String date) {
      // method that toString() can't find somehow
         StringTokenizer st = new StringTokenizer(date, "/", true);
         n = this.name;
         h = this.height;
      } 

      public String toString() { 
         return Kid(this.name, this.height, this.bDay);
      } 
   } //end class 

Ok, więc mój toString powyżej (wiem, mój trzeci parametr jest wyłączony, powinien być ciągiem znaków) jest wyłączony. Jeśli zakoduję wartość dla trzeciej rzeczy, to zwariuje i powie, że nie może tego znaleźć (powyżej). Więc jak mogę ustalić datę i podzielić to?

Klasa nazywająca to jest poniżej

class Driver {   
   public static void main (String[] args) {   
      Kid kid1 = new Kid("Lexie", 2.6, "11/5/2009");   
      System.out.println(kid1.toString());
   } //end main method 
} //end class  

Próbowałem znaleźć wiele konstruktorów i to naprawdę nie pomogło. Próbowałem poszukać informacjitoString() metody i próbowałem użyć toString()logiki poprzednich metod, którą stworzyłem wcześniej, ale ta jest zupełnie nowa, więc nigdy nie działała.

Wsparcie?

user1283885
źródło
5
Proszę podać kod pocztowy, który faktycznie by się skompilował. Twoja toString()metoda nie zwraca łańcucha i nie możesz wywołać takiego konstruktora. Nie jest jasne, co próbujesz osiągnąć. Przeczytaj tinyurl.com/so-hints i wyjaśnij swoje pytanie.
Jon Skeet
ToStringCreator wiosny ( github.com/SpringSource/spring-framework/tree/master/… ) wykonuje zadanie bardzo dobrze.
Ritesh
FYI, że strasznie kłopotliwe starych klas date-time, takie jak java.util.Date, java.util.GregorianCalendari java.text.SimpleDateFormatsą teraz spuścizny , wyparta przez java.time klas wbudowanych w Java 8 i późniejszych. Zobacz samouczek firmy Oracle .
Basil Bourque

Odpowiedzi:

134

toStringMa zwróci String.

public String toString() { 
    return "Name: '" + this.name + "', Height: '" + this.height + "', Birthday: '" + this.bDay + "'";
} 

Sugeruję, abyś użył funkcji swojego IDE do wygenerowania toStringmetody. Nie koduj go ręcznie.

Na przykład Eclipse może to zrobić, jeśli po prostu klikniesz prawym przyciskiem myszy kod źródłowy i wybierzesz Source > Generate toString

adarshr
źródło
1
To nie jest dobra praktyka, ponieważ używasz konkatenacji ciągów.
Amit
1
W takiej sytuacji lepszym wyborem jest StringBuilder.
Amit
9
@Amit Kompilator Java używa StringBuilderniejawnie. Nie ma problemu, chyba że używasz go w pętli.
chrylis
W Netbeans; jest pod, Source -> Insert Code...a następnie wybierztoString
Fer
10

Metoda toString () języka Java

Jeśli chcesz przedstawić dowolny obiekt jako ciąg znaków, powstaje metoda toString ().

Metoda toString () zwraca ciąg znaków reprezentujący obiekt.

Jeśli drukujesz dowolny obiekt, kompilator java wewnętrznie wywołuje na obiekcie metodę toString (). Zatem przesłanianie metody toString () zwraca żądane wyjście, może to być stan obiektu itp., Zależy od implementacji.

Zalety metody toString () w języku Java

Zastępując metodę toString () klasy Object, możemy zwrócić wartości obiektu, więc nie musimy pisać zbyt wiele kodu.

Wyjście bez metody toString ()

class Student{  
 int id;  
 String name;  
 String address;  

 Student(int id, String name, String address){  
 this.id=id;  
 this.name=name;  
 this.address=address;  
 }  

 public static void main(String args[]){  
   Student s1=new Student(100,”Joe”,”success”);  
   Student s2=new Student(50,”Jeff”,”fail”);  

   System.out.println(s1);//compiler writes here s1.toString()  
   System.out.println(s2);//compiler writes here s2.toString()  
 }  
}  

Output:Student@2kaa9dc
       Student@4bbc148

Możesz zobaczyć na powyższym przykładzie # 1. drukowanie s1 i s2 drukuje wartości Hashcode obiektów, ale chcę wydrukować wartości tych obiektów. Ponieważ kompilator java wewnętrznie wywołuje metodę toString (), nadpisanie tej metody zwróci określone wartości. Rozumiemy to na przykładzie podanym poniżej:

Example#2

Output with overriding toString() method

class Student{  
 int id;  
 String name;  
 String address;  

 Student(int id, String name, String address){  
 this.id=id;  
 this.name=name;  
 this.address=address;  
 }  

//overriding the toString() method  
public String toString(){ 
  return id+" "+name+" "+address;  
 }  
 public static void main(String args[]){  
   Student s1=new Student(100,”Joe”,”success”);  
   Student s2=new Student(50,”Jeff”,”fail”);  

   System.out.println(s1);//compiler writes here s1.toString()  
   System.out.println(s2);//compiler writes here s2.toString()  
 }  
} 

Output:100 Joe success
       50 Jeff fail

Zwróć uwagę, że toString () jest głównie związane z koncepcją polimorfizmu w Javie. W Eclipse, spróbuj kliknąć toString () i kliknij go prawym przyciskiem myszy, a następnie kliknij Open Declaration i zobacz, skąd pochodzi superclass toString ().

Linux Le
źródło
4

Możesz stworzyć nowy obiekt w toString (). posługiwać się

return "Name = " + this.name +" height= " + this.height;

zamiast

return Kid(this.name, this.height, this.bDay);

W razie potrzeby możesz zmienić zwracany ciąg znaków. Istnieją inne sposoby przechowywania daty zamiast kalandra.

sudmong
źródło
3

Nie możesz wywołać konstruktora tak, jakby to była normalna metoda, możesz go wywołać tylko za pomocą, newaby utworzyć nowy obiekt:

Kid newKid = new Kid(this.name, this.height, this.bDay);

Jednak tworzenie nowego obiektu z metody toString () nie jest tym, co chcesz robić.

Adrian Pronk
źródło
3

Jak wyjaśnili inni, toStringnie jest to miejsce do tworzenia instancji klasy. Zamiast tego toStringmetoda ma na celu zbudowanie łańcucha reprezentującego wartość instancji Twojej klasy, raportującego przynajmniej najważniejsze pola danych przechowywanych w tym obiekcie. W większości przypadków toStringsłuży do debugowania i rejestrowania, a nie do logiki biznesowej.

Aby wygenerować tekst reprezentujący wartość obiektu do wyświetlenia użytkownikowi, dodaj inną metodę. Ludzie często nazywają tę metodę w podobny sposób getDisplayName. Na przykład DayOfWeek::getDisplayNamei Month::getDisplayName.

StringJoiner

Począwszy od Java 8 i nowszych, najnowocześniejszym sposobem implementacji toStringbyłaby StringJoinerklasa. Jak mówi doktor:

StringJoiner służy do konstruowania sekwencji znaków oddzielonych separatorem i opcjonalnie rozpoczynających się od podanego przedrostka i kończących się podanym sufiksem.

Użyj w ten sposób:

@Override
public String toString ()
{
    return new StringJoiner(                           // In Java 8 and later, StringJoiner is used to construct a sequence of characters separated by a delimiter and optionally starting with a supplied prefix and ending with a supplied suffix.
                " | " ,                                // Delimiter
                Person.class.getSimpleName() + "[ " ,  // Prefix
                " ]"                                   // Suffix
            )
            .add( "name=" + name )                     // Append
            .add( "phone=" + phone )                   // Append
            .toString();                               // Convert entire sequence to a single `String` object.
}

Osoba [imię = Alicja | phone = 555.867.5309]

Basil Bourque
źródło
1
to jest bardziej eleganckie
esQmo_
2

Poniższy kod jest przykładem. Pytanie oparte na tym samym, zamiast korzystać z konwersji opartej na IDE, czy istnieje szybszy sposób implementacji, aby w przyszłości nastąpiły zmiany, nie musimy wielokrotnie modyfikować wartości?

@Override
    public String toString() {
        return "ContractDTO{" +
                "contractId='" + contractId + '\'' +
                ", contractTemplateId='" + contractTemplateId + '\'' +
                '}';
    }
RCR
źródło
2

Jeśli interesują Cię testy jednostkowe, możesz zadeklarować publiczny „ToStringTemplate”, a następnie przetestować jednostkę toString. Nawet jeśli nie wykonasz testów jednostkowych, myślę, że jest „czystszy” i używa formatu String.format.

public class Kid {

    public static final String ToStringTemplate = "KidName='%1s', Height='%2s', GregCalendar='%3s'";

    private String kidName;
    private double height;
    private GregorianCalendar gregCalendar;

    public String getKidName() {
        return kidName;
    }

    public void setKidName(String kidName) {
        this.kidName = kidName;
    }

    public double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }

    public GregorianCalendar getGregCalendar() {
        return gregCalendar;
    }

    public void setGregCalendar(GregorianCalendar gregCalendar) {
        this.gregCalendar = gregCalendar;
    }

    public String toString() { 
        return String.format(ToStringTemplate, this.getKidName(), this.getHeight(), this.getGregCalendar());
    } 
}

Teraz możesz wykonać test jednostkowy, tworząc Kid, ustawiając właściwości i wykonując własny string.format w ToStringTemplate i porównując.

uczynienie ToStringTemplate static-final oznacza „JEDNA WERSJA” prawdy, zamiast posiadania „kopii” szablonu w teście jednostkowym.

granadaCoder
źródło
1

Cóż, w rzeczywistości będziesz musiał zwrócić coś takiego, ponieważ toString musi zwrócić ciąg

public String toString() {
 return "Name :" + this.name + "whatever :" + this.whatever + "";
}

i faktycznie robisz coś złego w konstruktorze, ustawiasz zmienną ustawioną przez użytkownika na nazwę, podczas gdy musisz zrobić odwrotnie. Czego nie powinieneś robić

n = this.name

Co powinieneś zrobić

this.name = n

Mam nadzieję, że to pomoże, dzięki

Mohamed Sherif Noureldin
źródło
1

możemy nawet pisać w ten sposób, tworząc nowy obiekt String w klasie i przypisując mu to, co chcemy w konstruktorze i zwracając to w metodzie toString, która jest nadpisywana

public class Student{  
 int id;  
 String name;  
 String address;  
 String details;
 Student(int id, String name, String address){  
 this.id=id;  
 this.name=name;  
 this.address=address;  
 this.details=id+"  "+name+"  "+address;  
 }  

//overriding the toString() method  
public String toString(){ 
  return details;  
 }  
 public static void main(String args[]){  
   Student s1=new Student(100,"Joe","success");  
   Student s2=new Student(50,"Jeff","fail");  

   System.out.println(s1);//compiler writes here s1.toString()  
   System.out.println(s2);//compiler writes here s2.toString()  
 }  
}
user7321815
źródło
1

Zawsze miej łatwy sposób: Kliknij prawym przyciskiem myszy > Generuj > toString () > wybierz żądany szablon. wprowadź opis obrazu tutaj

logbasex
źródło
0

Moim zdaniem najlepszym sposobem jest użycie biblioteki google gson:

        @Override
public String toString() {
    return new GsonBuilder().setPrettyPrinting().create().toJson(this);
}

lub apache commons lang refleksyjny sposób

user666
źródło
0
  1. jeśli używasz notatnika: wtedy

    public String toString(){
    
     return ""; ---now here you can use variables which you have created for your class
    
    }
    
  2. jeśli używasz eclipse IDE, naciśnij

    -alt +shift +s 
    

    -kliknij na override toString, aby uzyskać opcje wyboru typu zmiennych, które chcesz wybrać.

Facet
źródło
0

Miłym i zwięzłym sposobem jest użycie adnotacji Lombok. Posiada @ToStringadnotację, która wygeneruje implementację toString()metody. Domyślnie wydrukuje nazwę klasy wraz z każdym polem w kolejności, oddzielone przecinkami. Możesz łatwo dostosować swoje dane wyjściowe, przekazując parametry do adnotacji, np .:

@ToString(of = {"name", "lastName"})

Co jest odpowiednikiem czystej Javy:

public String toString() {
        return "Person(name=" + this.name + ", lastName=" + this.experienceInYears + ")";
    }
żądło
źródło
0

Jeśli używasz tylko toString()do debugowania DTO , możesz automatycznie wygenerować czytelne dla człowieka dane wyjściowe za pomocą czegoś podobnego do następującego:

import com.fasterxml.jackson.databind.ObjectMapper;
...
public String toString() {
    try { return new ObjectMapper().writeValueAsString(this); }
    catch (Exception e) { return "{ObjectMapper failed}"; }
}

Nie jest to jednak odpowiednie w przypadku wdrożeń produkcyjnych, jeśli DTO może zawierać informacje umożliwiające identyfikację (które nie powinny być rejestrowane w dziennikach).

Brent Bradburn
źródło