Як правильно замінити toString () на Java?


87

Звучить трохи по-дурному, але мені потрібна допомога щодо мого toString()методу, і це дуже дратує. Я спробував шукати в Інтернеті, тому що toStringце той, де він викручується і "не знаходить конструктора малюків №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 вище (я знаю, мій третій параметр вимкнений, повинен бути Рядок) вимкнений. Якщо я твердо кодую значення для третьої речі, воно стає невдалим і каже, що не може знайти це (вгорі). То як я можу отримати дату та розбити її?

Клас, який називає це, наведено нижче

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()логіку методів, яку створив попередню, але це абсолютно нова, тому вона ніколи не працювала.

Допомога?


5
Будь ласка, поштовий індекс, який насправді компілюється. Ваш toString()метод не повертає рядок, і ви не можете так викликати конструктор. Незрозуміло, чого ви навіть намагаєтесь досягти. Будь ласка, прочитайте tinyurl.com/so-hints і поясніть своє запитання.
Джон Скіт,

ToStringCreator Spring ( github.com/SpringSource/spring-framework/tree/master/… ) робить цю роботу дуже гарно.
Ritesh

FYI, то дуже клопітно старі класи дати і часу , такі як java.util.Date, java.util.GregorianCalendarі java.text.SimpleDateFormatтепер спадщина , витіснений java.time класів , вбудованих в Java 8 і пізніших версій. Див. Підручник Oracle .
Василь Бурк,

Відповіді:


134

toStringПовинен повертати String.

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

Я пропоную вам скористатися функціями IDE для генерації toStringметоду. Не кодуйте його вручну.

Наприклад, Eclipse може це зробити, якщо просто клацнути правою кнопкою миші на вихідному коді та вибрати Source > Generate toString


1
Це не є доброю практикою, оскільки ви використовуєте конкатенацію рядків.
Amit

1
StringBuilder - кращий вибір у такій ситуації.
Amit

9
@Amit Компілятор Java використовує StringBuilderнеявно. Проблем немає, якщо ви не використовуєте їх у циклі.
chrisis

У Netbeans; це під Source -> Insert Code...тоді виберітьtoString
Фер

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 друкує значення об'єктів Hashcode, але я хочу надрукувати значення цих об'єктів. Оскільки компілятор 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 () і клацнути правою кнопкою миші, потім клацнути на Open Declaration і подивитися, звідки береться Суперклас toString ().


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

Людина [ім'я = Аліса | телефон = 555.867.5309]


1
це більш елегантно
esQmo_

2

Наступний код - зразок. Питання, засноване на тому самому, замість використання перетворення на основі IDE, чи є швидший спосіб реалізації, щоб у майбутньому відбулися зміни, нам не потрібно змінювати значення знову і знову?

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

2

Якщо ви зацікавлені в Unit-Tests, тоді ви можете оголосити загальнодоступний "ToStringTemplate", а потім ви можете Unit test у своєму 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 означає "ОДНУ ВЕРСІЮ" правди, а не наявність "копії" шаблону в модульному тесті.


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

1

Завжди майте простий спосіб: Клацніть правою кнопкою миші > Створити > toString () > виберіть потрібний шаблон. введіть тут опис зображення


0

На мою думку, найкращим способом є використання бібліотеки google gson:

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

або Apache Commons lang


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 
    

    -натисніть на метод перевизначення toString, тут ви отримаєте параметри вибору типу змінних, які ви хочете вибрати.


0

Гарним і стислим способом є використання анотацій Ломбока. Він має @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 може містити ідентифікаційну інформацію (яку не слід фіксувати в журналах).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.