如何在没有得到 "SomeType@2f92e0f4" 的情况下打印我的 Java 对象?
How do I print my Java object without getting "SomeType@2f92e0f4"?
我有一个class定义如下:
public class Person {
private String name;
// constructor and getter/setter omitted
}
我试图打印我的实例 class:
System.out.println(myPerson);
但我得到了以下输出:com.foo.Person@2f92e0f4
。
当我尝试打印 Person
个对象的数组时发生了类似的事情:
Person[] people = //...
System.out.println(people);
我得到了输出:[Lcom.foo.Person;@28a418fc
这个输出是什么意思?我如何更改此输出以使其包含我的人名?我如何打印我的对象集合?
注意:这是关于这个主题的规范问答。
背景
所有 Java object 都有一个 toString()
方法,当您尝试打印 object.
时调用该方法
System.out.println(myObject); // invokes myObject.toString()
这个方法定义在object的Object
class (the superclass of all Java objects). The Object.toString()
method returns a fairly ugly looking string, composed of the name of the class, an @
symbol and the hashcode中的十六进制。代码如下:
// Code of Object.toString()
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
结果如com.foo.MyType@2f92e0f4
因此可以解释为:
com.foo.MyType
- class 的名称,即 class 在包 com.foo
. 中是 MyType
@
- 将字符串连接在一起[=132=]
2f92e0f4
object. 的哈希码
数组的名称 classes 看起来有点不同,Class.getName()
的 Java 文档对此有很好的解释。例如,[Ljava.lang.String
表示:
[
- single-dimensional 数组(相对于 [[
或 [[[
等)
L
- 数组包含一个 class 或接口
java.lang.String
- 数组 中object的类型
自定义输出
要在您调用 System.out.println(myObject)
时打印不同的内容,您必须 override 您自己的 class 方法中的 toString()
方法。这是一个简单的例子:
public class Person {
private String name;
// constructors and other methods omitted
@Override
public String toString() {
return name;
}
}
现在如果我们打印 Person
,我们会看到他们的名字而不是 com.foo.Person@12345678
。
请记住,toString()
只是将 object 转换为字符串的 一种 方式。通常,此输出应以清晰简洁的方式完整描述您的 object。对于我们的 Person
class 更好的 toString()
可能是:
@Override
public String toString() {
return getClass().getSimpleName() + "[name=" + name + "]";
}
这将打印,例如 Person[name=Henry]
。这对 debugging/testing.
来说是非常有用的数据
如果您只想专注于 object 的一个方面或包含很多时髦的格式,您最好定义一个单独的方法,例如String toElegantReport() {...}
.
Auto-generating 输出
很多IDEs offer support for auto-generating a toString()
method, based on the fields in the class. See docs for Eclipse and IntelliJ,例如
几个流行的 Java 库也提供此功能。一些示例包括:
-
-
@ToString
annotation from Project Lombok
打印组 objects
您已经为您的 class 创建了一个不错的 toString()
。如果将 class 放入数组或 collection 中会发生什么?
数组
如果您有一个 object 数组,您可以调用 Arrays.toString()
来生成数组内容的简单表示。例如,考虑这个 Person
objects:
的数组
Person[] people = { new Person("Fred"), new Person("Mike") };
System.out.println(Arrays.toString(people));
// Prints: [Fred, Mike]
注意:这是对数组 class 中名为 toString()
的 static 方法的调用,这与我们一直在讨论的不同以上。
如果你有一个 multi-dimensional 数组,你可以使用 Arrays.deepToString()
来实现同样的输出。
Collections
大多数 collection 会根据对每个元素调用 .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 中的每个 class 默认情况下都有 toString()
方法,如果您将那个 class 的某个对象传递给 [=13=,则会调用该方法].默认情况下,此调用 returns 该对象的 className@hashcode。
{
SomeClass sc = new SomeClass();
// Class @ followed by hashcode of object in Hexadecimal
System.out.println(sc);
}
您可以覆盖 class 的 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);
}
}
我认为 apache 提供了一个更好的 util class 它提供了一个函数来获取字符串
ReflectionToStringBuilder.toString(object)
在 Eclipse 中,
转到您的class,
右击->源->生成toString()
;
它将覆盖 toString()
方法并打印 class 的对象。
如果您直接打印 Person 的任何对象,它将 ClassName@HashCode
写入代码。
在您的案例中 com.foo.Person@2f92e0f4
正在打印。其中Person
是对象所属的class,2f92e0f4
是对象的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());
}
}
在 intellij 中,您可以通过按 alt+inset 然后选择 toString() 来自动生成 toString 方法,这里是用于测试的输出 class:
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 +
'}';
}
}
如您所见,它通过连接 class 的几个属性生成一个字符串,对于基元,它将打印它们的值,对于引用类型,它将使用它们的 class 类型(在本例为 Test2 的字符串方法)。
如果您查看对象 class(Java 中所有 class 的父对象 class),则 toString() 方法实现是
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
每当您打印 Java 中的任何对象时,都会调用 toString()。现在由您决定是否覆盖 toString() 然后您的方法将调用其他对象 class 方法调用。
默认情况下,Java 中的每个对象都有 toString()
方法输出 ObjectType@HashCode。
如果您想要更多有意义的信息,那么您需要覆盖 class 中的 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);
打印人物对象时,它将打印人物的姓名,而不是 class 姓名和哈希码。
在第二种情况下,当您尝试打印数组时,它会打印 [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);
可能还有其他方法。希望这可以帮助。 :)
我更喜欢使用实用函数,它使用 GSON 将 Java 对象反序列化为 JSON 字符串。
/**
* This class provides basic/common functionalities to be applied on Java Objects.
*/
public final class ObjectUtils {
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
private ObjectUtils() {
throw new UnsupportedOperationException("Instantiation of this class is not permitted in case you are using reflection.");
}
/**
* This method is responsible for de-serializing the Java Object into Json String.
*
* @param object Object to be de-serialized.
* @return String
*/
public static String deserializeObjectToString(final Object object) {
return GSON.toJson(object);
}
}
我设法在 Spring 中使用 Jackson 完成了这项工作 5. 根据对象的不同,它可能并非在所有情况下都有效。
import com.fasterxml.jackson.databind.ObjectMapper;
ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.writeValueAsString(yourObject));
输出看起来像
{
"id" : 1,
"fieldOne" : "string"
}
Here 是使用 Jackson
的更多示例
如果你使用 GSON 它可能看起来像
Gson gson = new Gson();
System.out.println(gson.toJson(yourObject));
对于“深度”toString()
,有一个替代基于 JSON 的答案(Jackson、GSON 等):ReflectionToStringBuilder from the Apache Commons Lang 3 library, with RecursiveToStringStyle or MultilineRecursiveToStringStyle。代码示例:
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
]
]
如果您正在使用项目 Lombok,您可以使用 @ToString
注释并生成标准 toString()
方法,而无需添加样板文件。
import lombok.ToString;
@ToString
public class LoginDto {
private String user;
private String pass;
}
...
System.out.println(loginDto.toString());
// LoginDto(user=x@xxx.x, pass=xxxxx)
在 class 上使用 Lombok @Data 注释将提供 getter、setter、toString 和哈希码。使用 Lombok 更好,因为它可以处理样板代码。
我有一个class定义如下:
public class Person {
private String name;
// constructor and getter/setter omitted
}
我试图打印我的实例 class:
System.out.println(myPerson);
但我得到了以下输出:com.foo.Person@2f92e0f4
。
当我尝试打印 Person
个对象的数组时发生了类似的事情:
Person[] people = //...
System.out.println(people);
我得到了输出:[Lcom.foo.Person;@28a418fc
这个输出是什么意思?我如何更改此输出以使其包含我的人名?我如何打印我的对象集合?
注意:这是关于这个主题的规范问答。
背景
所有 Java object 都有一个 toString()
方法,当您尝试打印 object.
System.out.println(myObject); // invokes myObject.toString()
这个方法定义在object的Object
class (the superclass of all Java objects). The Object.toString()
method returns a fairly ugly looking string, composed of the name of the class, an @
symbol and the hashcode中的十六进制。代码如下:
// Code of Object.toString()
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
结果如com.foo.MyType@2f92e0f4
因此可以解释为:
com.foo.MyType
- class 的名称,即 class 在包com.foo
. 中是 @
- 将字符串连接在一起[=132=]2f92e0f4
object. 的哈希码
MyType
数组的名称 classes 看起来有点不同,Class.getName()
的 Java 文档对此有很好的解释。例如,[Ljava.lang.String
表示:
[
- single-dimensional 数组(相对于[[
或[[[
等)L
- 数组包含一个 class 或接口java.lang.String
- 数组 中object的类型
自定义输出
要在您调用 System.out.println(myObject)
时打印不同的内容,您必须 override 您自己的 class 方法中的 toString()
方法。这是一个简单的例子:
public class Person {
private String name;
// constructors and other methods omitted
@Override
public String toString() {
return name;
}
}
现在如果我们打印 Person
,我们会看到他们的名字而不是 com.foo.Person@12345678
。
请记住,toString()
只是将 object 转换为字符串的 一种 方式。通常,此输出应以清晰简洁的方式完整描述您的 object。对于我们的 Person
class 更好的 toString()
可能是:
@Override
public String toString() {
return getClass().getSimpleName() + "[name=" + name + "]";
}
这将打印,例如 Person[name=Henry]
。这对 debugging/testing.
如果您只想专注于 object 的一个方面或包含很多时髦的格式,您最好定义一个单独的方法,例如String toElegantReport() {...}
.
Auto-generating 输出
很多IDEs offer support for auto-generating a toString()
method, based on the fields in the class. See docs for Eclipse and IntelliJ,例如
几个流行的 Java 库也提供此功能。一些示例包括:
@ToString
annotation from Project Lombok
打印组 objects
您已经为您的 class 创建了一个不错的 toString()
。如果将 class 放入数组或 collection 中会发生什么?
数组
如果您有一个 object 数组,您可以调用 Arrays.toString()
来生成数组内容的简单表示。例如,考虑这个 Person
objects:
Person[] people = { new Person("Fred"), new Person("Mike") };
System.out.println(Arrays.toString(people));
// Prints: [Fred, Mike]
注意:这是对数组 class 中名为 toString()
的 static 方法的调用,这与我们一直在讨论的不同以上。
如果你有一个 multi-dimensional 数组,你可以使用 Arrays.deepToString()
来实现同样的输出。
Collections
大多数 collection 会根据对每个元素调用 .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 中的每个 class 默认情况下都有 toString()
方法,如果您将那个 class 的某个对象传递给 [=13=,则会调用该方法].默认情况下,此调用 returns 该对象的 className@hashcode。
{
SomeClass sc = new SomeClass();
// Class @ followed by hashcode of object in Hexadecimal
System.out.println(sc);
}
您可以覆盖 class 的 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);
}
}
我认为 apache 提供了一个更好的 util class 它提供了一个函数来获取字符串
ReflectionToStringBuilder.toString(object)
在 Eclipse 中,
转到您的class,
右击->源->生成toString()
;
它将覆盖 toString()
方法并打印 class 的对象。
如果您直接打印 Person 的任何对象,它将 ClassName@HashCode
写入代码。
在您的案例中 com.foo.Person@2f92e0f4
正在打印。其中Person
是对象所属的class,2f92e0f4
是对象的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());
}
}
在 intellij 中,您可以通过按 alt+inset 然后选择 toString() 来自动生成 toString 方法,这里是用于测试的输出 class:
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 +
'}';
}
}
如您所见,它通过连接 class 的几个属性生成一个字符串,对于基元,它将打印它们的值,对于引用类型,它将使用它们的 class 类型(在本例为 Test2 的字符串方法)。
如果您查看对象 class(Java 中所有 class 的父对象 class),则 toString() 方法实现是
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
每当您打印 Java 中的任何对象时,都会调用 toString()。现在由您决定是否覆盖 toString() 然后您的方法将调用其他对象 class 方法调用。
默认情况下,Java 中的每个对象都有 toString()
方法输出 ObjectType@HashCode。
如果您想要更多有意义的信息,那么您需要覆盖 class 中的 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);
打印人物对象时,它将打印人物的姓名,而不是 class 姓名和哈希码。
在第二种情况下,当您尝试打印数组时,它会打印 [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);
可能还有其他方法。希望这可以帮助。 :)
我更喜欢使用实用函数,它使用 GSON 将 Java 对象反序列化为 JSON 字符串。
/**
* This class provides basic/common functionalities to be applied on Java Objects.
*/
public final class ObjectUtils {
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
private ObjectUtils() {
throw new UnsupportedOperationException("Instantiation of this class is not permitted in case you are using reflection.");
}
/**
* This method is responsible for de-serializing the Java Object into Json String.
*
* @param object Object to be de-serialized.
* @return String
*/
public static String deserializeObjectToString(final Object object) {
return GSON.toJson(object);
}
}
我设法在 Spring 中使用 Jackson 完成了这项工作 5. 根据对象的不同,它可能并非在所有情况下都有效。
import com.fasterxml.jackson.databind.ObjectMapper;
ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.writeValueAsString(yourObject));
输出看起来像
{
"id" : 1,
"fieldOne" : "string"
}
Here 是使用 Jackson
的更多示例如果你使用 GSON 它可能看起来像
Gson gson = new Gson();
System.out.println(gson.toJson(yourObject));
对于“深度”toString()
,有一个替代基于 JSON 的答案(Jackson、GSON 等):ReflectionToStringBuilder from the Apache Commons Lang 3 library, with RecursiveToStringStyle or MultilineRecursiveToStringStyle。代码示例:
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
]
]
如果您正在使用项目 Lombok,您可以使用 @ToString
注释并生成标准 toString()
方法,而无需添加样板文件。
import lombok.ToString;
@ToString
public class LoginDto {
private String user;
private String pass;
}
...
System.out.println(loginDto.toString());
// LoginDto(user=x@xxx.x, pass=xxxxx)
在 class 上使用 Lombok @Data 注释将提供 getter、setter、toString 和哈希码。使用 Lombok 更好,因为它可以处理样板代码。