Como substituir toString () corretamente em Java?

87

Parece um pouco estúpido, mas preciso de ajuda no meu toString()método e é muito chato. Eu tentei pesquisar online porque toStringé aquele em que está bagunçando e "não encontrando o construtor Kid # 2", embora ele esteja lá e eu até faria outra coisa e não funcione. Ok, isso foi muito, então aqui está o meu 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, então meu toString acima (eu sei, meu terceiro parâmetro está desligado, deveria ser um String) está desligado. Se eu codificar um valor para a terceira coisa, ele fica confuso e diz que não pode encontrar isso (acima). Então, como posso saber a data e separá-la?

Chamada de classe está abaixo

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  

Tentei pesquisar vários construtores e realmente não ajudou. Eu tentei pesquisar toString()métodos e tentei usar a toString()lógica de métodos anteriores que criei anteriormente, mas isso é novo, então nunca funcionou.

Socorro?

user1283885
fonte
5
Por favor, poste o código que realmente compilaria. Seu toString()método não retorna uma string e você não pode chamar um construtor assim. Não está claro o que você está tentando alcançar. Leia tinyurl.com/so-hints e esclareça sua pergunta.
Jon Skeet
O ToStringCreator do Spring ( github.com/SpringSource/spring-framework/tree/master/… ) faz o trabalho muito bem.
Ritesh
Para sua informação, as classes de data e hora terrivelmente problemáticas como java.util.Date, java.util.GregorianCalendare java.text.SimpleDateFormatagora são legadas , suplantadas pelas classes java.time construídas no Java 8 e posterior. Veja o Tutorial da Oracle .
Basil Bourque

Respostas:

134

O toStringdeve retornar a String.

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

Eu sugiro que você use os recursos do seu IDE para gerar o toStringmétodo. Não o codifique manualmente.

Por exemplo, o Eclipse pode fazer isso se você simplesmente clicar com o botão direito do mouse no código-fonte e selecionar Source > Generate toString

Adarshr
fonte
1
Isso não é uma boa prática, pois você está usando concatenação de string.
Amit
1
StringBuilder é a melhor escolha em tal situação.
Amit
9
@Amit O compilador Java usa StringBuilderimplicitamente. Não há problema, a menos que você esteja usando em um loop.
chrylis
No Netbeans; está abaixo de Source -> Insert Code...então selecionetoString
Fer
10

Método Java toString ()

Se você quiser representar qualquer objeto como uma string, o método toString () passa a existir.

O método toString () retorna a representação de string do objeto.

Se você imprimir qualquer objeto, o compilador java invoca internamente o método toString () no objeto. Portanto, sobrescrever o método toString () retorna a saída desejada, pode ser o estado de um objeto etc. depende de sua implementação.

Vantagem do método toString () Java

Substituindo o método toString () da classe Object, podemos retornar valores do objeto, portanto, não precisamos escrever muito código.

Saída sem 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

Você pode ver no exemplo # 1 acima. imprimir s1 e s2 imprime os valores de Hashcode dos objetos, mas eu quero imprimir os valores desses objetos. Como o compilador java chama internamente o método toString (), a sobrescrita desse método retornará os valores especificados. Vamos entender com o exemplo abaixo:

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

Observe que toString () está relacionado principalmente ao conceito de polimorfismo em Java. Em, Eclipse, tente clicar em toString () e clicar com o botão direito nele. Em seguida, clique em Open Declaration e veja de onde vem a Superclasse toString ().

Linux Le
fonte
4

Você pode criar um novo objeto no toString (). usar

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

ao invés de

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

Você pode alterar a string de retorno conforme necessário. Existem outras maneiras de armazenar data em vez de calandrar.

Sudmong
fonte
3

Você não pode chamar um construtor como se fosse um método normal, você só pode chamá-lo com newpara criar um novo objeto:

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

Mas construir um novo objeto a partir do seu método toString () não é o que você deseja fazer.

Adrian Pronk
fonte
3

Como outros explicaram, o toStringnão é o lugar para instanciar sua classe. Em vez disso, o toStringmétodo se destina a construir uma string que representa o valor de uma instância de sua classe, relatando pelo menos os campos de dados mais importantes armazenados nesse objeto. Na maioria dos casos, toStringé usado para depuração e registro, não para sua lógica de negócios.

Para gerar texto representando o valor de um objeto para exibição a um usuário, adicione outro método. As pessoas costumam nomear o método de maneira semelhante getDisplayName. Por exemplo, DayOfWeek::getDisplayNamee Month::getDisplayName.

StringJoiner

A partir do Java 8 e posterior, a forma mais moderna de implementação toStringseria usar a StringJoinerclasse. Como diz o doc:

StringJoiner é usado para construir uma sequência de caracteres separados por um delimitador e opcionalmente começando com um prefixo fornecido e terminando com um sufixo fornecido.

Use assim:

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

Pessoa [nome = Alice | telefone = 555.867.5309]

Basil Bourque
fonte
1
que é mais elegante
esQmo_
2

O código a seguir é um exemplo. Pergunta baseada na mesma, em vez de usar a conversão baseada em IDE, há uma maneira mais rápida de implementar para que no futuro as mudanças ocorram, não precisamos modificar os valores repetidamente?

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

Se você estiver interessado em testes de unidade, poderá declarar um "ToStringTemplate" público e, em seguida, poderá testar a unidade de seu toString. Mesmo se você não fizer o teste de unidade, acho que é "mais limpo" e 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());
    } 
}

Agora você pode testar a unidade criando o Kid, definindo as propriedades e fazendo seu próprio string.format no ToStringTemplate e comparando.

fazer ToStringTemplate static-final significa "UMA VERSÃO" da verdade, ao invés de ter uma "cópia" do modelo no teste de unidade.

granadaCoder
fonte
1

Bem, na verdade você precisará retornar algo assim porque toString deve retornar uma string

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

e você realmente fizer algo errado no construtor, você definirá a variável que o usuário definiu para o nome enquanto você precisa fazer o oposto. O que você não deveria fazer

n = this.name

O que você deveria fazer

this.name = n

Espera que isso ajude, obrigado

Mohamed Sherif Noureldin
fonte
1

podemos até escrever assim criando um novo objeto String na classe e atribuindo a ele o que quisermos no construtor e retornar isso no método toString que é sobrescrito

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
fonte
1

Sempre tenha um jeito fácil: Clique com o botão direito > Gerar > toString () > selecione o modelo que você deseja. insira a descrição da imagem aqui

logbasex
fonte
0

A melhor maneira, na minha opinião, é usar a biblioteca gson do Google:

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

ou Apache commons lang forma de reflexão

usuário666
fonte
0
  1. se você estiver usando o bloco de notas: então

    public String toString(){
    
     return ""; ---now here you can use variables which you have created for your class
    
    }
    
  2. se você estiver usando Eclipse IDE, pressione

    -alt +shift +s 
    

    -clique em substituir o método toString aqui, você obterá opções para selecionar o tipo de variáveis ​​que deseja selecionar.

O cara
fonte
0

Uma maneira agradável e concisa é usar anotações do Lombok. Possui @ToStringanotação, que irá gerar uma implementação do toString()método. Por padrão, ele imprimirá o nome da sua classe, junto com cada campo, em ordem, separados por vírgulas. Você pode personalizar facilmente sua saída passando parâmetros para anotação, por exemplo:

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

O que é equivalente ao Java puro:

public String toString() {
        return "Person(name=" + this.name + ", lastName=" + this.experienceInYears + ")";
    }
ferrão
fonte
0

Se você estiver usando apenas toString()para depurar um DTO , poderá gerar uma saída legível por humanos automaticamente com algo como o seguinte:

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

No entanto, isso não é apropriado para implantações de produção se o DTO puder conter PII (que não devem ser capturados em logs).

Brent Bradburn
fonte