如何在不获取“SomeType @ 2f92e0f4”的情况下打印我的Java对象?

时间:2015-03-19 08:59:18

标签: java string object tostring

我的课程定义如下:

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

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

注意:这是关于此主题的规范Q& A.

12 个答案:

答案 0 :(得分:357)

背景

所有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 - 班级的名称,即班级MyType中的班级为com.foo
  • @ - 将字符串连接在一起
  • 2f92e0f4对象的哈希码。

数组类的名称看起来有点不同,这在Class.getName()的Javadoc中得到了很好的解释。例如,[Ljava.lang.String表示:

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

自定义输出

要在致电System.out.println(myObject)时打印不同的内容,您必须在自己的班级中使用override toString()方法。这是一个简单的例子:

public class Person {

  private String name;

  // constructors and other methods omitted

  @Override
  public String toString() {
    return name;
  }
}

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

请记住,toString()只是一种方式,可以将对象转换为字符串。通常,此输出应以清晰简洁的方式完整描述您的对象。我们toString()课程的Person更好{/ 1}}可能是:

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

将打印哪个,例如Person[name=Henry]。这是用于调试/测试的非常有用的数据。

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


自动生成输出

许多IDEs支持根据类中的字段自动生成toString()方法。例如,请参阅EclipseIntelliJ的文档。

一些流行的Java库也提供此功能。一些例子包括:


打印对象组

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

阵列

如果您有一个对象数组,则可以调用Arrays.toString()来生成数组内容的简单表示。例如,考虑这个Person对象数组:

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

// Prints: [Fred, Mike]

注意:这是对Arrays类中名为toString()静态方法的调用,这与我们上面讨论的不同。

如果您有多维数组,则可以使用Arrays.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(),如上所述。

答案 1 :(得分:43)

我认为apache提供了一个更好的util类,它提供了一个获取字符串

的函数
ReflectionToStringBuilder.toString(object)

答案 2 :(得分:26)

默认情况下,Java中的每个类都有toString()方法,如果将该类的某个对象传递给System.out.println(),则会调用该方法。默认情况下,此调用返回该对象的className @ hashcode。

{
    SomeClass sc = new SomeClass();
    // Class @ followed by hashcode of object in Hexadecimal
    System.out.println(sc);
}

您可以覆盖类的toString方法以获得不同的输出。见这个例子

class A {
    String s = "I am just a object";
    @Override
    public String toString()
    {
        return s;
    }
}

class B {
    public static void main(String args[])
    {
        A obj = new A();
        System.out.println(obj);
    }
}

答案 3 :(得分:8)

在Eclipse中 去你的班级, 右键单击 - &gt; source-&gt;生成toString();

它将覆盖toString()方法并打印该类的对象。

答案 4 :(得分:4)

在intellij中,您可以通过按alt + inset自动生成toString方法,然后选择toString()这里是测试类的输出:

public class test  {
int a;
char b;
String c;
Test2 test2;

@Override
public String toString() {
    return "test{" +
            "a=" + a +
            ", b=" + b +
            ", c='" + c + '\'' +
            ", test2=" + test2 +
            '}';
 }
}

正如您所看到的,它通过连接类的几个属性生成一个String,对于它将打印其值的基元,对于引用类型,它将使用它们的类类型(在本例中为Test2的字符串方法)。

答案 5 :(得分:4)

默认情况下,Java中的每个Object都有toString()方法,该方法输出ObjectType @HashCode。

如果您想要更有意义的信息,那么您需要覆盖班级中的toString()方法。

public class Person {
  private String name;

  // constructor and getter/setter omitted

  // overridding toString() to print name
  public String toString(){
     return name;  
  }
}

现在,当您使用System.out.prtinln(personObj);打印人物对象时,它将打印人物的名称而不是类名和哈希码。

在第二种情况下,当您尝试打印数组时,它会打印[Lcom.foo.Person;@28a418fc数组类型及其哈希码。

如果要打印人名,有很多方法。

您可以编写自己的函数来迭代每个人并打印

void printPersonArray(Person[] persons){
    for(Person person: persons){
        System.out.println(person);
    }
}

您可以使用Arrays.toString()打印它。这对我来说似乎最简单。

 System.out.println(Arrays.toString(persons));
 System.out.println(Arrays.deepToString(persons));  // for nested arrays  

您可以使用java 8方式打印它(使用流和方法引用)。

 Arrays.stream(persons).forEach(System.out::println);

也可能有其他方式。希望这可以帮助。 :)

答案 6 :(得分:3)

如果你直接打印人物的任何物体它将ClassName@HashCode代码。

在您的情况下com.foo.Person@2f92e0f4正在打印。其中Person是对象所属的类,2f92e0f4是Object的hashCode。

public class Person {
  private String name;

  public Person(String name){
  this.name = name;
  }
  // getter/setter omitted

   @override
   public String toString(){
        return name;
   }
}

现在,如果您尝试使用Person的对象,则会打印名称

Class Test
 {
  public static void main(String... args){
    Person obj = new Person("YourName");
    System.out.println(obj.toString());
  }
}

答案 7 :(得分:3)

我更喜欢使用实用程序函数,该函数使用GSON将Java对象反序列化为JSON字符串。

10.10.2017 23:59:59

答案 8 :(得分:2)

如果查看Object类(Java中所有类的Parent类),toString()方法实现是

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

无论何时用Java打印任何对象,都会调用toString()。现在,如果你覆盖toString(),那么你的方法会调用其他的Object类方法调用。

答案 9 :(得分:0)

在春季5,我设法使用Jackson完成了这一任务。根据对象的不同,杰克逊可能无法在所有情况下都起作用。

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

ObjectMapper mapper = new ObjectMapper();
Staff staff = createStaff();
// pretty print
String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(staff);
System.out.println("-------------------------------------------------------------------")
System.out.println(json);
System.out.println("-------------------------------------------------------------------")

输出类似于

-------------------------------------------------------------------
{
  "id" : 1,
  "internalStaffId" : "1",
  "staffCms" : 1,
  "createdAt" : "1",
  "updatedAt" : "1",
  "staffTypeChange" : null,
  "staffOccupationStatus" : null,
  "staffNote" : null
}
-------------------------------------------------------------------

使用Jackson here

的更多示例

您也可以尝试GSON。应该是这样的:

Gson gson = new Gson();
System.out.println(gson.toJson(objectYouWantToPrint).toString());

答案 10 :(得分:0)

对于“深度”toString(),有一个替代基于 JSON 的答案(Jackson、GSON 等):ReflectionToStringBuilder 来自 Apache Commons Lang 3 库,带有 RecursiveToStringStyleMultilineRecursiveToStringStyle。代码示例:

System.out.println("My object: " +
    ReflectionToStringBuilder.toString(theObject, new RecursiveToStringStyle()));

输出示例:

// RecursiveToStringStyle
Person@7f54[name=Stephen,age=29,smoker=false,job=Job@43cd2[title=Manager]]

// MultilineRecursiveToStringStyle
Person@7f54[
  name=Stephen,
  age=29,
  smoker=false,
  job=Job@43cd2[
    title=Manager
  ]
]

答案 11 :(得分:-2)

Arrays.deepToString(arrayOfObject)

上面的函数打印不同基元对象的数组。

[[AAAAA, BBBBB], [6, 12], [2003-04-01 00:00:00.0, 2003-10-01 00:00:00.0], [2003-09-30 00:00:00.0, 2004-03-31 00:00:00.0], [Interim, Interim], [2003-09-30, 2004-03-31]];