我有一个定义如下的类:

public class Person {
  private String name;

  // constructor and getter/setter omitted
}

我试图打印我的类的一个实例:

System.out.println(myPerson);

但我得到了以下结果:com.foo.Person@2f92e0f4.

当我试图打印一个包含Person个对象的数组时,也发生了类似的事情:

Person[] people = //...
System.out.println(people); 

我得到了输出:[Lcom.foo.Person;@28a418fc

此输出意味着什么?如何更改此输出以使其包含我的人名?如何打印我的对象集合?

Note:这是关于此主题的规范问答.

推荐答案

Background

所有Java对象都有一个toString()方法,当您试图打印对象时会调用该方法.

System.out.println(myObject);  // invokes myObject.toString()

这个方法是在Object类(所有Java对象的超类)中定义的.Object.toString()方法返回一个相当难看的字符串,由类的名称、@符号和对象的hashcode组成,以十六进制表示.代码如下所示:

// Code of Object.toString()
public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

因此,com.foo.MyType@2f92e0f4这样的结果可以解释为:

  • com.foo.MyType-类的名称,即包com.foo中的类是MyType.
  • @-将绳子连接在一起
  • 2f92e0f4对象的哈希码.

数组类的名称看起来有点不同,这在Javadocs for Class.getName()中有很好的解释.例如,[Ljava.lang.String意味着:

  • [-一维数组(与[[[[[等不同)
  • L-数组包含一个类或接口
  • java.lang.String-数组中对象的类型

Customizing the Output

要在调用System.out.println(myObject)时打印不同的内容,必须在自己的类中使用toString()方法.下面是一个简单的例子:

public class Person {

  private String name;
  
  // constructors and other methods omitted
  
  @Override
  public String toString() {
    return name;
  }
}

现在如果我们打印Person,我们看到的是他们的名字,而不是com.foo.Person@12345678.

请记住,toString()只是将对象转换为字符串的one种方式.通常,此输出应该以清晰而简明的方式完整地描述您的对象.对于我们Person班来说,更好的toString()可能是:

@Override
public String toString() {
  return getClass().getSimpleName() + "[name=" + name + "]";
}

其将打印例如Person[name=Henry].对于调试/测试来说,这是一条非常有用的数据.

如果您只想关注对象的一个方面,或者包含大量的爵士格式,那么最好定义一个单独的方法,例如String toElegantReport() {...}.


Auto-generating the Output

许多IDEs提供了基于类中的字段自动生成toString()方法的支持.例如,请参阅EclipseIntelliJ的文档.

几个流行的Java库也提供此功能.一些示例包括:


Printing groups of objects

所以你为你的班级创造了一个不错的toString()分.如果将该类放入数组或集合中会发生什么?

数组

如果您有一个对象数组,则可以调用array.toString()来生成数组内容的简单表示形式.例如,考虑以下包含Person个对象的数组:

Person[] people = { new Person("Fred"), new Person("Mike") };
System.out.println(array.toString(people));

// Prints: [Fred, Mike]

注意:这是对数组类中名为toString()static方法的调用,这与我们上面讨论的不同.

如果你有一个multi-dimensional array,你可以用array.deepToString()来实现同样的输出.

集合

大多数集合都会在每个元素上调用.toString()的基础上产生一个漂亮的输出.

List<Person> people = new ArrayList<>();
people.add(new Person("Alice"));
people.add(new Person("Bob"));    
System.out.println(people);

// Prints [Alice, Bob]

所以你只需要确保你的列表元素定义了一个不错的toString(),如上所述.

Java相关问答推荐

我们如何直接使用kerminldap服务票证来通过ldap进行身份验证并形成LDAP上下文

Spring Webocket:尽管凭据设置为False,但MLhttpsify和Fetch请求之间的CORS行为存在差异

scanner 如何在执行hasNextLine一次后重新读取整个文件?

如果一个子类没有构造函数,超类也没有构造函数,那么为什么我可以构造子类的实例呢?

neo4j java驱动程序是否会在错误发生时自动回滚事务?

从Spring5迁移到Spring6:无法在雅加达包中找到类

将java.util.Date转换为OffsetDateTime

使用UTC时区将startDatetime转换为本地时间

如何在代码中将行呈现在矩形前面?

buildDir:File!&#的getter解决方案是什么?39.被抛弃

如何在透视表中添加对计数列的筛选?

Android Studio模拟器没有互联网

在Eclipse中可以使用外部字体吗?

为什么项目名称出现在我的GET请求中?

在Java中将对象&转换为&q;HashMap(&Q)

H2数据库仅支持%1个结果集?

控制器建议异常处理

按长度排序字符串数组

Eureka客户端无法使用用户/通行证注册到Eureka服务器

转换为JSON字符串时,日期按天递减-Java