จะแทนที่ toString () อย่างถูกต้องใน Java ได้อย่างไร?


88

ฟังดูโง่ไปหน่อย แต่ฉันต้องการความช่วยเหลือเกี่ยวกับtoString()วิธีการของฉันและมันน่ารำคาญมาก ฉันพยายามค้นหาทางออนไลน์เพราะtoStringเป็นสิ่งที่ทำให้สับสนและ "ไม่พบ Kid constructor # 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และชี้แจงคำถามของคุณ
— Jon Skeet

ToStringCreator ของ Spring ( github.com/SpringSource/spring-framework/tree/master/… ) ทำงานได้ดีมาก
— พิธี

FYI, ลำบากชะมัดเก่าชั้นเรียนวันที่เวลาเช่นjava.util.Date, java.util.GregorianCalendarและjava.text.SimpleDateFormatตอนนี้มรดกแทนที่โดยjava.timeชั้นเรียนที่สร้างขึ้นใน Java 8 และต่อมา ดูการสอนโดยออราเคิล
— Basil Bourque

คำตอบ:


136

ควรจะกลับมาเป็นtoStringString

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

ฉันขอแนะนำให้คุณใช้ประโยชน์จากคุณสมบัติของ IDE เพื่อสร้างtoStringวิธีการนี้ อย่าเขียนโค้ดด้วยมือ

ตัวอย่างเช่น Eclipse สามารถทำได้หากคุณเพียงแค่คลิกขวาที่ซอร์สโค้ดแล้วเลือก Source > Generate toString


1
นี่ไม่ใช่แนวทางปฏิบัติที่ดีเนื่องจากคุณใช้การต่อสายอักขระ
— Amit

1
StringBuilder เป็นทางเลือกที่ดีกว่าในสถานการณ์เช่นนี้
— มิต

9
@Amit คอมไพเลอร์ Java ใช้StringBuilderโดยปริยาย ไม่มีปัญหาเว้นแต่คุณจะใช้แบบวนซ้ำ
— chrylis -cautiouslyoptimistic-

ใน Netbeans; อยู่ภายใต้Source -> Insert Code...แล้วเลือกtoString
— Fer

11

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 และดูว่า Superclass 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

หากคุณสนใจการทดสอบหน่วยคุณสามารถประกาศ "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 หมายถึง "ONE VERSION" ของความจริงแทนที่จะมี "สำเนา" ของเทมเพลตในการทดสอบหน่วย


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คำอธิบายประกอบซึ่งจะสร้างการใช้งานtoString()วิธีการ โดยค่าเริ่มต้นจะพิมพ์ชื่อชั้นเรียนของคุณพร้อมกับแต่ละฟิลด์ตามลำดับโดยคั่นด้วยเครื่องหมายจุลภาค คุณสามารถปรับแต่งผลลัพธ์ของคุณได้อย่างง่ายดายโดยส่งผ่านพารามิเตอร์ไปยังคำอธิบายประกอบเช่น:

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

ซึ่งเทียบเท่ากับ Java บริสุทธิ์:

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

1

หากคุณแค่ใช้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 (ซึ่งไม่ควรบันทึกไว้ในบันทึก)


1

มีวิธีง่ายๆเสมอ: คลิกขวา > สร้าง > toString () > เลือกเทมเพลตที่คุณต้องการ ใส่คำอธิบายภาพที่นี่


0

วิธีที่ดีที่สุดในความคิดของฉันคือการใช้ห้องสมุด google gson:

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

หรือ apache commons lang reflect way


0
  1. หากคุณใช้งานโดยใช้ notepad: แล้ว

    public String toString(){
    
     return ""; ---now here you can use variables which you have created for your class
    
    }
    
  2. หากคุณใช้ eclipse IDE ให้กด

    -alt +shift +s 
    

    - คลิกที่วิธีการแทนที่ toString ที่นี่คุณจะได้รับตัวเลือกในการเลือกประเภทของตัวแปรที่คุณต้องการเลือก

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.