如何在Java中使用toString方法?

123

有人可以解释一下在Object类中定义的toString()方法的概念吗?它如何使用,其目的是什么?


5
重复的问题:https://dev59.com/WXE95IYBdhLWcg3wY9D6和http://stackoverflow.com/questions/2887640/what-is-the-use-of-tostring-in-java - pavanlimo
以下是一个快速的技巧/快速实现方式: @Override public String toString() { return org.apache.commons.lang3.builder.ToStringBuilder.reflectionToString(this); } - granadaCoder
13个回答

85

根据Object.toString文档:

返回对象的字符串表示形式。通常,toString方法返回一个文本上表示该对象的字符串。结果应该是简洁但信息丰富的表示方式,并且易于人们阅读。建议所有子类都覆盖此方法。

Object类的toString方法返回一个字符串,该字符串包括对象所属类的名称、艾特符号“@”和对象哈希码的无符号十六进制表示法。换句话说,此方法返回一个等于以下值的字符串:

getClass().getName() + '@' + Integer.toHexString(hashCode())

例子:

String[] mystr ={"a","b","c"};
System.out.println("mystr.toString: " + mystr.toString());

output:- mystr.toString: [Ljava.lang.String;@13aaa14a

1
主要目的是在子类中覆盖它。我认为@stephen和Andreas_D的答案比被接受的答案更好。 - Sree Rama

40

使用 String.toString

每当您需要以 String 的形式查看所调用的构造函数的值时,可以简单地使用 String.toString... 例如:

package pack1;

import java.util.*;

class Bank {

    String n;
    String add;
    int an;
    int bal;
    int dep;

    public Bank(String n, String add, int an, int bal) {

        this.add = add;
        this.bal = bal;
        this.an = an;
        this.n = n;

    }

    public String toString() {
        return "Name of the customer.:" + this.n + ",, "
                + "Address of the customer.:" + this.add + ",, " + "A/c no..:"
                + this.an + ",, " + "Balance in A/c..:" + this.bal;
    }
}

public class Demo2 {

    public static void main(String[] args) {

        List<Bank> l = new LinkedList<Bank>();

        Bank b1 = new Bank("naseem1", "Darbhanga,bihar", 123, 1000);
        Bank b2 = new Bank("naseem2", "patna,bihar", 124, 1500);
        Bank b3 = new Bank("naseem3", "madhubani,bihar", 125, 1600);
        Bank b4 = new Bank("naseem4", "samastipur,bihar", 126, 1700);
        Bank b5 = new Bank("naseem5", "muzafferpur,bihar", 127, 1800);
        l.add(b1);
        l.add(b2);
        l.add(b3);
        l.add(b4);
        l.add(b5);
        Iterator<Bank> i = l.iterator();
        while (i.hasNext()) {
            System.out.println(i.next());
        }
    }

}

...将此程序复制到您的Eclipse中,运行它......您将了解有关String.toString的想法...


5
我希望你知道toString不是用于UI目的的,也不适合用于UI。 - Powerslave
@Powerslave,能否解释一下为什么所有的Swing组件都使用toString来在GUI中显示对象?如果我有一个复杂的对象并想在GUI中展示它,那么我不会为此创建额外的渲染器,也不会从对象中提取字符串属性来在GUI中使用,我会保持简单,并实现toString以避免所有这些开销。如果您想以更清晰的方式实现此目的,请创建一个专门用于UI目的的包装类,并实现其toString方法以返回wrappee的字符串属性。 - Timmos
1
@Timmos 如果你的朋友跳桥,你会跟着跳吗?仅仅因为Swing开发人员使用(读作; 滥用)toString函数并不意味着你也应该这样做。 - Toby Caulk
2
这绝对是最简单的方法,只要您继续使用默认的Swing API即可完成工作。如果您想要自定义渲染,那么可以在组件上安装自定义渲染器。如果您只想显示由字符串表示的对象,则实现toString()比自定义渲染器要容易得多,后者有各种陷阱需要正确处理。我认为你将其与跳桥进行比较很奇怪。 - Timmos

39
toString()方法返回一个对象的文本表示。在java.lang.Object中已经包含了一个基本的实现,因此由于所有对象都继承自java.lang.Object,所以可以保证每个Java对象都有此方法。
覆盖该方法总是一个好主意,特别是在调试时,因为调试器通常通过toString()方法的结果显示对象。因此,请使用有意义的实现,但仅限于技术目的。应用程序逻辑应使用getter方法:
public class Contact {
  private String firstName;
  private String lastName;
  public Contact (String firstName, String lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }
  public String getFirstName() {return firstName;}
  public String getLastName() {return lastName;}

  public String getContact() {
    return firstName + " " + lastName;
  }

  @Override
  public String toString() {
    return "["+getContact()+"]";
  }
}

17

它可能在应用程序的上下文中有可选的用途,但更常见的是用于调试目的。例如,在IDE中遇到断点时,阅读对象的有意义的toString()比检查其成员要容易得多。

toString()方法没有固定的要求。按照惯例,它通常会告诉您类的名称和相关数据成员的值。大多数情况下,toString()方法都是在IDE中自动生成的。

依赖于toString()方法的特定输出或在程序内解析它是不明智的。无论您做什么,请不要走这条路。


3
你能详细说明一下你上次说的话吗? - Jean-Philippe Caruana
@Jean-PhilippeCaruana toString方法旨在用于调试和日志记录,供程序员和系统管理员内部使用。toString方法不适用于向用户呈现,也不适用于提供适合解析的可靠结构化值。toString的实现往往会随着其包含类的演变而改变。为了向用户呈现,请添加一个像getDisplayName这样的方法。为了提供结构化可解析内容,请添加一个名称指示该结构规范的方法,例如formatDairyAssociationQuarterlyReportItem - Basil Bourque
@Jean-PhilippeCaruana Javadoc 所承诺的 Object::toString 合同声明:字符串输出不一定随时间或 JVM 调用而稳定。 因此,根据定义,不适合可靠解析。 - Basil Bourque

12

toString() 返回对象的字符串/文本表示。 toString() 方法通常用于诊断目的,例如调试、记录等,用于读取有关对象的有意义的详细信息。

当对象传递给 println、print、printf、String.format()、assert 或字符串连接运算符时,会自动调用该方法。

Object 类中 toString() 的默认实现返回一个字符串,其中包含此对象的类名,后跟 @ 符号和此对象的哈希码的无符号十六进制表示,使用以下逻辑:

getClass().getName() + "@" + Integer.toHexString(hashCode())

例如,以下内容。
public final class Coordinates {

    private final double x;
    private final double y;

    public Coordinates(double x, double y) {
        this.x = x;
        this.y = y;
    }

    public static void main(String[] args) {
        Coordinates coordinates = new Coordinates(1, 2);
        System.out.println("Bourne's current location - " + coordinates);
    }
}

打印
Bourne's current location - Coordinates@addbf1 //concise, but not really useful to the reader

现在,通过以下方式覆盖 Coordinates 类中的 toString() 方法:
@Override
public String toString() {
    return "(" + x + ", " + y + ")";
}

导致

Bourne's current location - (1.0, 2.0) //concise and informative

当调用包含对这些对象的引用的集合上的toString()方法时,覆盖toString()的有用性变得更加重要。例如,以下内容:
public static void main(String[] args) {
    Coordinates bourneLocation = new Coordinates(90, 0);
    Coordinates bondLocation = new Coordinates(45, 90);
    Map<String, Coordinates> locations = new HashMap<String, Coordinates>();
    locations.put("Jason Bourne", bourneLocation);
    locations.put("James Bond", bondLocation);
    System.out.println(locations);
}

打印

{James Bond=(45.0, 90.0), Jason Bourne=(90.0, 0.0)}

代替这个。
{James Bond=Coordinates@addbf1, Jason Bourne=Coordinates@42e816}

一些实现要点,
  1. You should almost always override the toString() method. One of the cases where the override wouldn't be required is utility classes that group static utility methods, in the manner of java.util.Math. The case of override being not required is pretty intuitive; almost always you would know.
  2. The string returned should be concise and informative, ideally self-explanatory.
  3. At least, the fields used to establish equivalence between two different objects i.e. the fields used in the equals() method implementation should be spit out by the toString() method.
  4. Provide accessors/getters for all of the instance fields that are contained in the string returned. For example, in the Coordinates class,

    public double getX() {
        return x;
    }
    public double getY() {
        return y;
    }
    

有关toString()方法的全面介绍,请参见Josh Bloch的《Effective Java™, Second Edition》第10章。


5
无论何时您在字符串上下文中访问对象(不是字符串),编译器都会在幕后调用toString()方法。
这就是为什么。
Map map = new HashMap();
System.out.println("map=" + map);

通过在您自己的类中重写Object中的标准toString(),您可以使您的对象在字符串上下文中也变得有用。

(并将其视为黑匣子!永远不要将内容用于除呈现给人类以外的任何其他目的)


4

编码:

public class Test {

    public static void main(String args[]) {

        ArrayList<Student> a = new ArrayList<Student>();
        a.add(new Student("Steve", 12, "Daniel"));
        a.add(new Student("Sachin", 10, "Tendulkar"));

        System.out.println(a);

        display(a);

    }

    static void display(ArrayList<Student> stu) {

        stu.add(new Student("Yuvi", 12, "Bhajji"));

        System.out.println(stu);

    }

}

Student.java:

public class Student {

    public String name;

    public int id;

    public String email;

    Student() {

    }

    Student(String name, int id, String email) {

        this.name = name;
        this.id = id;
        this.email = email;

    }

     public String toString(){           //using these toString to avoid the output like this [com.steve.test.Student@6e1408, com.steve.test.Student@e53108]
          return name+" "+id+" "+email;     
         }  


    public String getName(){

        return name;
    }

    public void setName(String name){

        this.name=name;
    }

    public int getId(){

        return id;
    }

    public void setId(int id){

        this.id=id;
    }

    public String getEmail(){

        return email;

    }

    public void setEmail(String email){

        this.email=email;
    }
}

输出:

[史蒂夫12丹尼尔,萨钦10滕度卡尔]

[史蒂夫12丹尼尔,萨钦10滕度卡尔,Yuvi 12 Bhajji]

如果在Pojo(Student.java)类中没有使用toString()方法,您将会得到如下的输出:[com.steve.test.Student@6e1408, com.steve.test.Student@e53108]。为了避免这些问题,我们使用toString()方法。


4

正确覆盖toString方法可以帮助Java的日志记录和调试。


3
除了Cletus在调试方面所回答的内容之外,当你输出一个对象时,它也会被使用,例如当你使用:
 System.out.println(myObject);

或者

System.out.println("text " + myObject);

2
toString的主要目的是生成对象的字符串表示形式,也就是返回值总是一个字符串。在大多数情况下,这通常是对象的类和包名,但在一些特殊情况下(如StringBuilder),你将得到实际的字符串文本。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接