Как правильно переопределить toString () в Java?

87

Звучит немного глупо, но мне нужна помощь по моему toString()методу, и это очень раздражает. Я попытался поискать в Интернете, потому что toStringэто тот, где он лажает и «не находит конструктор Kid # 2», хотя он есть, и я бы даже сделал что-то еще, и он не работает. Хорошо, это было много, вот мой код:

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 

Хорошо. Итак, мой toString выше (я знаю, что мой третий параметр выключен, должен быть String) выключен. Если я жестко запрограммирую значение для третьей вещи, она выходит из строя и говорит, что не может ее найти (вверху). Итак, как я могу назначить дату и разбить ее?

Класс, вызывающий это, находится ниже

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  

Я пробовал исследовать несколько конструкторов, и это действительно не помогло. Я пробовал исследовать toString()методы и пробовал использовать предыдущую toString()логику методов, которую я создал ранее, но это совершенно новый метод, поэтому он никогда не работал.

Помогите?

user1283885
источник
5
Пожалуйста, разместите код, который действительно будет компилироваться. Ваш toString()метод не возвращает строку, и вы не можете вызвать такой конструктор. Непонятно, чего вы вообще пытаетесь достичь. Пожалуйста, прочтите tinyurl.com/so-hints и уточните свой вопрос.
Джон Скит,
ToStringCreator Spring ( github.com/SpringSource/spring-framework/tree/master/… ) отлично справляется со своей задачей.
Ритеш
К вашему сведению, ужасно неприятные старые классы даты и времени, такие как java.util.Date, java.util.GregorianCalendarи java.text.SimpleDateFormatтеперь унаследованы , вытеснены классами java.time, встроенными в Java 8 и более поздних версий . См. Учебник Oracle .
Basil

Ответы:

134

toStringДолжен возвращать String.

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

Я предлагаю вам использовать возможности вашей IDE для создания toStringметода. Не кодируйте это вручную.

Например, Eclipse может сделать это, если вы просто щелкните правой кнопкой мыши исходный код и выберите Source > Generate toString

Адаршр
источник
1
Это не очень хорошая практика, поскольку вы используете конкатенацию строк.
Амит
1
StringBuilder - лучший выбор в такой ситуации.
Амит
9
@Amit Компилятор Java использует StringBuilderнеявно. Нет проблем, если вы не используете его в цикле.
chrylis -cautiouslyoptimistic- 06
В Netbeans; это ниже, Source -> Insert Code...затем выберитеtoString
Fer
10

Java toString () метод

Если вы хотите представить какой-либо объект в виде строки, появляется метод toString ().

Метод toString () возвращает строковое представление объекта.

Если вы печатаете какой-либо объект, java-компилятор внутренне вызывает метод toString () для этого объекта. Таким образом, переопределение метода toString () возвращает желаемый результат, это может быть состояние объекта и т. Д., В зависимости от вашей реализации.

Преимущество метода Java toString ()

Переопределив метод toString () класса Object, мы можем возвращать значения объекта, поэтому нам не нужно писать много кода.

Вывод без метода 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

Вы можете видеть в приведенном выше примере №1. печать s1 и s2 печатает значения хэш-кода объектов, но я хочу распечатать значения этих объектов. Поскольку компилятор java внутренне вызывает метод toString (), переопределение этого метода вернет указанные значения. Давайте разберемся с этим на примере, приведенном ниже:

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

Обратите внимание, что toString () в основном связано с концепцией полиморфизма в Java. В Eclipse попробуйте щелкнуть toString () и щелкнуть по нему правой кнопкой мыши. Затем щелкните «Открыть объявление» и посмотрите, откуда берется суперкласс toString ().

Linux Le
источник
4

Вы можете создать новый объект в toString (). использовать

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

вместо того

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

При необходимости вы можете изменить возвращаемую строку. Есть и другие способы сохранить дату вместо каландра.

судмонг
источник
3

Вы не можете вызвать конструктор, как если бы это был обычный метод, вы можете вызвать его только с помощью newдля создания нового объекта:

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

Но создание нового объекта из вашего метода toString () - это не то, чем вы хотите заниматься.

Адриан Пронк
источник
3

Как объясняли другие, toStringэто не место для создания экземпляра вашего класса. Вместо этого toStringметод предназначен для построения строки, представляющей значение экземпляра вашего класса, с отчетом по крайней мере о наиболее важных полях данных, хранящихся в этом объекте. В большинстве случаев toStringиспользуется для отладки и ведения журнала, а не для вашей бизнес-логики.

Чтобы сгенерировать текст, представляющий значение объекта для отображения пользователю, добавьте еще один метод. Люди часто называют этот метод чем-то вроде getDisplayName. Например, DayOfWeek::getDisplayNameи Month::getDisplayName.

StringJoiner

Начиная с Java 8 и более поздних версий, самый современный способ реализации - toStringиспользовать StringJoinerкласс. Как говорится в документе:

StringJoiner используется для создания последовательности символов, разделенных разделителем и, возможно, начиная с предоставленного префикса и заканчивая предоставленным суффиксом.

Используйте так:

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

Человек [имя = Алиса | phone = 555.867.5309]

Василий Бурк
источник
1
это более элегантно
esQmo_
2

Следующий код - это образец. Вопрос, основанный на том же, вместо использования преобразования на основе IDE, есть ли более быстрый способ реализации, чтобы в будущем изменения происходили, и нам не нужно было изменять значения снова и снова?

@Override
    public String toString() {
        return "ContractDTO{" +
                "contractId='" + contractId + '\'' +
                ", contractTemplateId='" + contractTemplateId + '\'' +
                '}';
    }
RCR
источник
2

Если вас интересуют модульные тесты, вы можете объявить общедоступный «ToStringTemplate», а затем выполнить модульное тестирование своего toString. Даже если вы не тестируете его, я думаю, что он «чище» и использует 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());
    } 
}

Теперь вы можете выполнить модульное тестирование, создав Kid, задав свойства и выполнив свой собственный string.format в ToStringTemplate и сравнив.

создание ToStringTemplate static-final означает «ОДНУ ВЕРСИЮ» истины, а не наличие «копии» шаблона в модульном тесте.

GranadaCoder
источник
1

На самом деле вам нужно будет вернуть что-то вроде этого, потому что toString должен вернуть строку

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

и вы действительно делаете что-то неправильно в конструкторе, вы устанавливаете переменную, которую пользователь установил для имени, в то время как вам нужно сделать наоборот. Чего не следует делать

n = this.name

Что ты должен делать

this.name = n

Надеюсь, это поможет, спасибо

Мохамед Шериф Нурелдин
источник
1

мы даже можем написать так, создав новый объект String в классе и назначив ему то, что мы хотим в конструкторе, и вернуть это в метод toString, который переопределен

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
источник
1

Всегда есть простой способ: щелкните правой кнопкой мыши > Создать > toString () > выберите нужный шаблон. введите описание изображения здесь

logbasex
источник
0

На мой взгляд, лучший способ - использовать библиотеку google gson:

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

или способ отражения apache commons lang

user666
источник
0
  1. если вы используете блокнот: тогда

    public String toString(){
    
     return ""; ---now here you can use variables which you have created for your class
    
    }
    
  2. если вы используете eclipse IDE, нажмите

    -alt +shift +s 
    

    -щелкните здесь метод override toString, вы получите возможность выбрать тип переменных, которые вы хотите выбрать.

Парень
источник
0

Хороший и лаконичный способ - использовать аннотации Lombok. Он имеет @ToStringаннотацию, которая будет генерировать реализацию toString()метода. По умолчанию он будет печатать имя вашего класса вместе с каждым полем по порядку, разделенные запятыми. Вы можете легко настроить свой вывод, передав параметры в аннотацию, например:

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

Что эквивалентно чистой Java:

public String toString() {
        return "Person(name=" + this.name + ", lastName=" + this.experienceInYears + ")";
    }
жало
источник
0

Если вы используете только toString()для отладки DTO , вы можете автоматически сгенерировать удобочитаемый вывод, используя что-то вроде следующего:

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

Однако это не подходит для производственных развертываний, если DTO может содержать PII (который не должен фиксироваться в журналах).

Брент Брэдберн
источник