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

Dun*_*nes 283 java string object tostring

我有一个类定义如下:

public class Person {
  private String name;

  // constructor and getter/setter omitted
}
Run Code Online (Sandbox Code Playgroud)

我试图打印我的班级实例:

System.out.println(myPerson);
Run Code Online (Sandbox Code Playgroud)

但我得到了以下输出:com.foo.Person@2f92e0f4.

当我尝试打印一个Person对象数组时发生了类似的事情:

Person[] people = //...
System.out.println(people); 
Run Code Online (Sandbox Code Playgroud)

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

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

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

Dun*_*nes 379

背景

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

System.out.println(myObject);  // invokes myObject.toString()
Run Code Online (Sandbox Code Playgroud)

此方法在Object类(所有Java对象的超类)中定义.该Object.toString()方法返回一个相当难看的字符串,由类的名称,@符号和十六进制对象的哈希码组成.这个代码看起来像:

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

com.foo.MyType@2f92e0f4因此可以将结果解释为:

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

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

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

自定义输出

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

public class Person {

  private String name;

  // constructors and other methods omitted

  @Override
  public String toString() {
    return name;
  }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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


自动生成输出

许多IDEtoString()根据类中的字段提供对自动生成方法的支持.例如,请参阅EclipseIntelliJ的文档.

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


打印对象组

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

数组

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

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

// Prints: [Fred, Mike]
Run Code Online (Sandbox Code Playgroud)

注意:这是对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]
Run Code Online (Sandbox Code Playgroud)

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


Roh*_*h K 46

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

ReflectionToStringBuilder.toString(object)
Run Code Online (Sandbox Code Playgroud)

  • 这样做的好处是它不需要编辑类,这有时是不可能的.但是,我如何递归打印嵌套对象呢? (5认同)
  • @lukas84 ReflectionToStringBuilder.toString(输入, new RecursiveToStringStyle()); 这也会打印嵌套对象 (5认同)

小智 33

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

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

您可以覆盖类的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);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这是一个简短易懂的答案,但为了说明OP为什么将`[Lcom.foo.Person; @ 28a418fc`”作为输出:这也是`toString()`方法的输出,但在运行时针对类型“ Person []”而非“ Person”生成的类中实现(请参见http://stackoverflow.com/a/8546532/1542343)。 (2认同)

ket*_*nkk 10

在Eclipse中,转到您的班级,右键单击 - > source-> Generate toString();

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


Mr.*_*r.Q 6

在 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 +
            '}';
 }
}
Run Code Online (Sandbox Code Playgroud)

如您所见,它通过连接类的几个属性来生成一个字符串,对于基元,它将打印它们的值,对于引用类型,它将使用它们的类类型(在这种情况下是 Test2 的字符串方法)。


adn*_*911 6

默认情况下,Java 中的每个对象都有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;  
  }
}
Run Code Online (Sandbox Code Playgroud)

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

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


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

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

void printPersonArray(Person[] persons){
    for(Person person: persons){
        System.out.println(person);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

 System.out.println(Arrays.toString(persons));
 System.out.println(Arrays.deepToString(persons));  // for nested arrays  
Run Code Online (Sandbox Code Playgroud)

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

 Arrays.stream(persons).forEach(System.out::println);
Run Code Online (Sandbox Code Playgroud)

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


Vik*_*yap 5

如果您直接打印 Person 的任何对象,它将打印ClassName@HashCode到代码中。

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

public class Person {
  private String name;

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

   @override
   public String toString(){
        return name;
   }
}
Run Code Online (Sandbox Code Playgroud)

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

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


小智 5

我更喜欢使用一个实用程序函数,该函数使用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);
    }
}
Run Code Online (Sandbox Code Playgroud)