Come sovrascrivere correttamente toString () in Java?


88

Sembra un po 'stupido, ma ho bisogno di aiuto sul mio toString()metodo ed è molto fastidioso. Ho provato a cercare online perché toStringè quello in cui sta rovinando e "non trova Kid costruttore n. 2" anche se è lì e vorrei anche fare qualcos'altro e non funziona. Ok, era molto quindi ecco il mio codice:

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 Quindi il mio toString sopra (lo so, il mio terzo parametro è disattivato, dovrebbe essere una stringa) è disattivato. Se codifico un valore per la terza cosa, va in tilt e dice che non riesce a trovarlo (sopra). Quindi come posso ottenere la data e romperla?

La classe che chiama questo è sotto

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  

Ho provato a ricercare più costruttori e davvero non ha aiutato. Ho provato a ricercare toString()metodi e ho provato a utilizzare la toString()logica dei metodi precedenti che ho creato in precedenza, ma questo è nuovo di zecca, quindi non ha mai funzionato.

Aiuto?


5
Si prega di inserire il codice che verrebbe effettivamente compilato. Il tuo toString()metodo non restituisce una stringa e non puoi chiamare un costruttore come quello. Non è chiaro nemmeno cosa stai cercando di ottenere. Si prega di leggere tinyurl.com/so-hints e chiarire la tua domanda.
Jon Skeet

ToStringCreator di Spring ( github.com/SpringSource/spring-framework/tree/master/… ) fa il lavoro molto bene.
Ritesh

Cordiali saluti, le vecchie classi data-ora terribilmente problematiche come java.util.Date, java.util.GregorianCalendare java.text.SimpleDateFormatora sono legacy , soppiantate dalle classi java.time incorporate in Java 8 e versioni successive. Vedi Tutorial di Oracle .
Basil Bourque,

Risposte:


136

La toStringdeve restituire una String.

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

Ti suggerisco di utilizzare le funzionalità del tuo IDE per generare il toStringmetodo. Non codificarlo a mano.

Ad esempio, Eclipse può farlo se fai semplicemente clic con il pulsante destro del mouse sul codice sorgente e seleziona Source > Generate toString


1
Questa non è una buona pratica, poiché stai usando la concatenazione di stringhe.
Amit

1
StringBuilder è una scelta migliore in una situazione del genere.
Amit

9
@Amit Il compilatore Java utilizza StringBuilderimplicitamente. Non c'è problema a meno che non lo utilizzi in un ciclo.
chrylis -cautiouslyoptimistic-

In Netbeans; è sotto Source -> Insert Code...quindi selezionatoString
Fer

11

Metodo Java toString ()

Se vuoi rappresentare qualsiasi oggetto come una stringa, il metodo toString () nasce.

Il metodo toString () restituisce la rappresentazione di stringa dell'oggetto.

Se si stampa un oggetto, il compilatore java richiama internamente il metodo toString () sull'oggetto. Quindi sovrascrivendo il metodo toString (), restituisce l'output desiderato, può essere lo stato di un oggetto ecc. Dipende dalla tua implementazione.

Vantaggio del metodo Java toString ()

Sovrascrivendo il metodo toString () della classe Object, possiamo restituire i valori dell'oggetto, quindi non abbiamo bisogno di scrivere molto codice.

Uscita senza il metodo 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

Puoi vedere nell'esempio n. 1 sopra. la stampa di s1 e s2 stampa i valori Hashcode degli oggetti ma voglio stampare i valori di questi oggetti. Poiché il compilatore java chiama internamente il metodo toString (), l'override di questo metodo restituirà i valori specificati. Comprendiamolo con l'esempio riportato di seguito:

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

Notare che toString () è principalmente correlato al concetto di polimorfismo in Java. In Eclipse, prova a fare clic su toString () e fai clic con il pulsante destro del mouse su di esso, quindi fai clic su Open Declaration e guarda da dove proviene la Superclass toString ().


4

Puoi creare un nuovo oggetto in toString (). uso

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

invece di

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

È possibile modificare la stringa di ritorno come richiesto. Ci sono altri modi per memorizzare la data invece di un calendario.


3

Non puoi chiamare un costruttore come se fosse un metodo normale, puoi solo chiamarlo con newper creare un nuovo oggetto:

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

Ma costruire un nuovo oggetto dal tuo metodo toString () non è quello che vuoi fare.


3

Come altri hanno spiegato, toStringnon è il posto giusto per creare un'istanza della tua classe. Invece, il toStringmetodo ha lo scopo di costruire una stringa che rappresenta il valore di un'istanza della tua classe, riportando almeno i campi di dati più importanti memorizzati in quell'oggetto. Nella maggior parte dei casi, toStringviene utilizzato per il debug e la registrazione, non per la logica aziendale.

Per generare testo che rappresenti il ​​valore di un oggetto da visualizzare a un utente, aggiungi un altro metodo. Le persone spesso chiamano il metodo qualcosa di simile getDisplayName. Ad esempio, DayOfWeek::getDisplayNamee Month::getDisplayName.

StringJoiner

A partire da Java 8 e versioni successive, il modo più moderno per implementare toStringutilizza la StringJoinerclasse. Come dice il dottore:

StringJoiner viene utilizzato per costruire una sequenza di caratteri separati da un delimitatore e facoltativamente che inizia con un prefisso fornito e termina con un suffisso fornito.

Usa in questo modo:

@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.
}

Persona [nome = Alice | telefono = 555.867.5309]


1
è più elegante
esQmo_

2

Il codice seguente è un esempio. Domanda basata sullo stesso, invece di utilizzare la conversione basata su IDE, esiste un modo più rapido per implementare in modo che in futuro si verifichino i cambiamenti, non abbiamo bisogno di modificare i valori più e più volte?

@Override
    public String toString() {
        return "ContractDTO{" +
                "contractId='" + contractId + '\'' +
                ", contractTemplateId='" + contractTemplateId + '\'' +
                '}';
    }

2

Se sei interessato agli unit test, puoi dichiarare un "ToStringTemplate" pubblico e quindi puoi eseguire un test unitario del tuo toString. Anche se non lo fai unit-test, penso che sia "più pulito" e utilizzi 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());
    } 
}

Ora puoi eseguire un test unitario creando Kid, impostando le proprietà e facendo il tuo string.format su ToStringTemplate e confrontando.

rendere ToStringTemplate statico-finale significa "UNA VERSIONE" della verità, piuttosto che avere una "copia" del modello nello unit-test.


1

Bene, in realtà dovrai restituire qualcosa di simile perché toString deve restituire una stringa

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

e in realtà fai qualcosa di sbagliato nel costruttore, imposti la variabile che l'utente ha impostato sul nome mentre devi fare il contrario. Cosa non dovresti fare

n = this.name

Cosa dovresti fare

this.name = n

Spero che questo aiuti grazie


1

possiamo anche scrivere in questo modo creando un nuovo oggetto String nella classe e assegnandogli quello che vogliamo nel costruttore e restituendolo nel metodo toString che viene sovrascritto

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

1

Un modo carino e conciso è usare le annotazioni di Lombok. Ha @ToStringun'annotazione, che genererà un'implementazione del toString()metodo. Per impostazione predefinita, stamperà il nome della tua classe, insieme a ogni campo, in ordine, separati da virgole. Puoi personalizzare facilmente l'output passando i parametri all'annotazione, ad esempio:

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

Che è equivalente a Java puro:

public String toString() {
        return "Person(name=" + this.name + ", lastName=" + this.experienceInYears + ")";
    }

1

Se stai usando solo toString()per il debug di un DTO , puoi generare automaticamente un output leggibile dall'uomo con qualcosa di simile al seguente:

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

Tuttavia, questo non è appropriato per le distribuzioni di produzione se il DTO può contenere informazioni personali (che non devono essere acquisite nei log).


1

Avere sempre un modo semplice: fare clic con il tasto destro > Genera > toString () > selezionare il modello che si desidera. inserisci qui la descrizione dell'immagine


0

Il modo migliore secondo me è usare la libreria Google Gson:

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

o apache commons lang riflessione modo


0
  1. se usi il blocco note: allora

    public String toString(){
    
     return ""; ---now here you can use variables which you have created for your class
    
    }
    
  2. se stai usando eclipse IDE, premi

    -alt +shift +s 
    

    -fai clic su override toString method qui otterrai le opzioni per selezionare il tipo di variabili che desideri selezionare.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.