¿Cómo anular toString () correctamente en Java?

87

Suena un poco estúpido, pero necesito ayuda con mi toString()método y es muy irritante. Intenté buscar en línea porque toStringes en el que se está cagando y "no encuentro el constructor de Kid # 2" aunque está allí e incluso haría otra cosa y no funciona. Ok, eso fue mucho, así que aquí está mi código:

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 Entonces mi toString anterior (lo sé, mi tercer parámetro está desactivado, debería ser una cadena) está desactivado. Si codifico un valor para la tercera cosa, se vuelve loco y dice que no puede encontrar esto (arriba). Entonces, ¿cómo puedo conseguir la fecha y romperla?

La clase que llama a esto está debajo

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  

Intenté investigar varios constructores y realmente no ayudó. Intenté investigar toString()métodos e intenté usar la toString()lógica de métodos anteriores que creé anteriormente, pero esto es nuevo, por lo que nunca funcionó.

¿Ayuda?

usuario1283885
fuente
5
Publique el código que realmente se compilaría. Su toString()método no devuelve una cadena y no puede llamar a un constructor como ese. No está claro lo que está tratando de lograr. Lea tinyurl.com/so-hints y aclare su pregunta.
Jon Skeet
ToStringCreator de Spring ( github.com/SpringSource/spring-framework/tree/master/… ) hace el trabajo muy bien.
Ritesh
Para su información, las clases de fecha y hora antiguas terriblemente problemáticas como java.util.Date, java.util.GregorianCalendary java.text.SimpleDateFormatahora son heredadas , suplantadas por las clases java.time integradas en Java 8 y versiones posteriores. Consulte el tutorial de Oracle .
Basil Bourque

Respuestas:

134

Se toStringsupone que devuelve un String.

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

Le sugiero que utilice las funciones de su IDE para generar el toStringmétodo. No lo codifique a mano.

Por ejemplo, Eclipse puede hacerlo si simplemente hace clic con el botón derecho en el código fuente y selecciona Source > Generate toString

Adarshr
fuente
1
Esta no es una buena práctica, ya que está utilizando la concatenación de cadenas.
Amit
1
StringBuilder es una mejor opción en tal situación.
Amit
9
@Amit El compilador de Java utiliza StringBuilderimplícitamente. No hay problema a menos que lo esté usando en un bucle.
chrylis -cautelyoptimistic-
En Netbeans; está debajo y Source -> Insert Code...luego seleccionetoString
Fer
10

Método Java toString ()

Si desea representar cualquier objeto como una cadena, el método toString () aparece.

El método toString () devuelve la representación de cadena del objeto.

Si imprime cualquier objeto, el compilador de Java invoca internamente el método toString () en el objeto. Entonces, anular el método toString (), devuelve la salida deseada, puede ser el estado de un objeto, etc.depende de su implementación.

Ventaja del método Java toString ()

Al anular el método toString () de la clase Object, podemos devolver valores del objeto, por lo que no necesitamos escribir mucho código.

Salida sin método 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

Puede ver en el ejemplo # 1 anterior. la impresión de s1 y s2 imprime los valores Hashcode de los objetos, pero quiero imprimir los valores de estos objetos. Dado que el compilador de Java llama internamente al método toString (), anular este método devolverá los valores especificados. Entendamos con el ejemplo que se da a continuación:

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

Tenga en cuenta que toString () está relacionado principalmente con el concepto de polimorfismo en Java. En Eclipse, intente hacer clic en toString () y haga clic derecho sobre él. Luego, haga clic en Abrir declaración y vea de dónde proviene la Superclase toString ().

Linux Le
fuente
4

Puede crear un nuevo objeto en toString (). utilizar

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

en vez de

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

Puede cambiar la cadena de retorno según sea necesario. Hay otras formas de almacenar la fecha en lugar del calendario.

sudmong
fuente
3

No puede llamar a un constructor como si fuera un método normal, solo puede llamarlo con newpara crear un nuevo objeto:

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

Pero construir un nuevo objeto a partir de su método toString () no es lo que quiere hacer.

Adrian Pronk
fuente
3

Como otros explicaron, toStringno es el lugar para crear instancias de su clase. En cambio, el toStringmétodo está destinado a construir una cadena que represente el valor de una instancia de su clase, informando sobre al menos los campos de datos más importantes almacenados en ese objeto. En la mayoría de los casos, toStringse utiliza para depurar y registrar, no para su lógica empresarial.

Para generar texto que represente el valor de un objeto para mostrarlo a un usuario, agregue otro método. La gente suele nombrar el método con algo así getDisplayName. Por ejemplo, DayOfWeek::getDisplayNamey Month::getDisplayName.

StringJoiner

A partir de Java 8 y posteriores, la forma más moderna de implementar toStringsería usar la StringJoinerclase. Como dice el doc:

StringJoiner se utiliza para construir una secuencia de caracteres separados por un delimitador y, opcionalmente, comenzando con un prefijo proporcionado y terminando con un sufijo proporcionado.

Use así:

@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 [nombre = Alice | teléfono = 555.867.5309]

Albahaca Bourque
fuente
1
eso es más elegante
esQmo_
2

El siguiente código es una muestra. Pregunta basada en la misma, en lugar de usar la conversión basada en IDE, ¿hay una forma más rápida de implementar para que en el futuro ocurran los cambios, no necesitemos modificar los valores una y otra vez?

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

Si está interesado en las pruebas unitarias, puede declarar una "ToStringTemplate" pública y, a continuación, puede realizar una prueba unitaria de su toString. Incluso si no lo prueba por unidad, creo que es "más limpio" y usa 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());
    } 
}

Ahora puede realizar pruebas unitarias creando Kid, estableciendo las propiedades y haciendo su propio formato string.format en ToStringTemplate y comparando.

hacer que ToStringTemplate static-final signifique "UNA VERSIÓN" de la verdad, en lugar de tener una "copia" de la plantilla en la prueba unitaria.

granadaCoder
fuente
1

Bueno, en realidad, deberá devolver algo como esto porque toString tiene que devolver una cadena

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

y en realidad haces algo mal en el constructor, estableces la variable que el usuario estableció en el nombre mientras necesitas hacer lo contrario. Lo que no deberías hacer

n = this.name

Que deberías hacer

this.name = n

Espera que esto ayude gracias

Mohamed Sherif Noureldin
fuente
1

incluso podemos escribir así creando un nuevo objeto String en la clase y asignándole lo que queramos en el constructor y devolviéndolo en el método toString que se anula

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()  
 }  
}
usuario7321815
fuente
1

Siempre tenga una manera fácil: haga clic con el botón derecho > Generar > toString () > seleccione la plantilla que desee. ingrese la descripción de la imagen aquí

logbasex
fuente
0

En mi opinión, la mejor manera es usar la biblioteca gson de Google:

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

o apache commons lang reflexión forma

usuario666
fuente
0
  1. si está usando el bloc de notas: entonces

    public String toString(){
    
     return ""; ---now here you can use variables which you have created for your class
    
    }
    
  2. si está utilizando eclipse IDE, presione

    -alt +shift +s 
    

    -haga clic en el método override toString aquí obtendrá opciones para seleccionar qué tipo de variables desea seleccionar.

El tipo
fuente
0

Una forma agradable y concisa es usar las anotaciones de Lombok. Tiene @ToStringanotación, que generará una implementación del toString()método. De forma predeterminada, imprimirá el nombre de su clase, junto con cada campo, en orden, separados por comas. Puede personalizar fácilmente su salida pasando parámetros a la anotación, por ejemplo:

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

Que es equivalente a Java puro:

public String toString() {
        return "Person(name=" + this.name + ", lastName=" + this.experienceInYears + ")";
    }
aguijón
fuente
0

Si solo está utilizando toString()para depurar un DTO , puede generar una salida legible por humanos automáticamente con algo como lo siguiente:

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

Sin embargo, esto no es apropiado para implementaciones de producción si el DTO puede contener PII (que no debe capturarse en registros).

Brent Bradburn
fuente