Làm cách nào để in đối tượng Java của tôi mà không nhận được Một số loạiType @ 2f92e0f4?


301

Tôi có một lớp được định nghĩa như sau:

public class Person {
  private String name;

  // constructor and getter/setter omitted
}

Tôi đã cố gắng để in một ví dụ của lớp học của tôi:

System.out.println(myPerson);

nhưng tôi đã nhận được đầu ra sau : com.foo.Person@2f92e0f4.

Một điều tương tự đã xảy ra khi tôi cố in một mảng các Personđối tượng:

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

Tôi đã nhận được đầu ra: [Lcom.foo.Person;@28a418fc

Sản lượng này có nghĩa là gì? Làm cách nào để thay đổi đầu ra này để nó chứa tên của người tôi? Và làm thế nào để tôi in các bộ sưu tập các đối tượng của tôi?

Lưu ý : đây là mục đích hỏi đáp kinh điển về chủ đề này.


1
Bạn có thể sử dụng thư viện GSON để chuyển đổi đối tượng thành json và ngược lại. Rất hữu ích để gỡ lỗi.
Ashish Rawat

Câu trả lời:


403

Lý lịch

Tất cả các đối tượng Java có một toString()phương thức, được gọi khi bạn thử và in đối tượng.

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

Phương thức này được định nghĩa trong Objectlớp (siêu lớp của tất cả các đối tượng Java). Các Object.toString()phương thức trả về một chuỗi tìm kiếm khá xấu xí, bao gồm các tên của lớp, một @biểu tượng và hashcode của đối tượng trong hệ thập lục phân. Mã cho điều này trông giống như:

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

Do đó, một kết quả như com.foo.MyType@2f92e0f4có thể được giải thích là:

  • com.foo.MyType - tên của lớp, tức là lớp nằm MyTypetrong gói com.foo.
  • @ - nối chuỗi với nhau
  • 2f92e0f4 mã băm của đối tượng.

Tên của các lớp mảng trông hơi khác nhau, được giải thích tốt trong Javadocs cho Class.getName(). Chẳng hạn, [Ljava.lang.Stringcó nghĩa là:

  • [- một mảng một chiều (trái ngược với [[hoặc [[[v.v.)
  • L - mảng chứa một lớp hoặc giao diện
  • java.lang.String - loại đối tượng trong mảng

Tùy chỉnh đầu ra

Để in một cái gì đó khác nhau khi bạn gọi System.out.println(myObject), bạn phải ghi đè các toString()phương thức trong lớp của riêng bạn. Đây là một ví dụ đơn giản:

public class Person {

  private String name;

  // constructors and other methods omitted

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

Bây giờ nếu chúng ta in một Person, chúng ta thấy tên của họ chứ không phải com.foo.Person@12345678.

Hãy nhớ rằng đó toString()chỉ là một cách để một đối tượng được chuyển đổi thành một chuỗi. Thông thường, đầu ra này sẽ mô tả đầy đủ đối tượng của bạn một cách rõ ràng và súc tích. Một tốt hơn toString()cho chúng ta Personlớp có thể là:

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

Mà sẽ in, ví dụ , Person[name=Henry]. Đó là một phần dữ liệu thực sự hữu ích để gỡ lỗi / kiểm tra.

Nếu bạn muốn tập trung vào chỉ một khía cạnh của đối tượng của bạn hoặc bao gồm nhiều định dạng vui nhộn, bạn có thể tốt hơn để xác định một phương thức riêng thay vào đó, ví dụ String toElegantReport() {...}.


Tự động tạo đầu ra

Nhiều IDE cung cấp hỗ trợ cho việc tự động tạo một toString()phương thức, dựa trên các trường trong lớp. Xem tài liệu cho EclipseIntelliJ , ví dụ.

Một số thư viện Java phổ biến cũng cung cấp tính năng này. Một số ví dụ bao gồm:


Nhóm in đối tượng

Vì vậy, bạn đã tạo ra một tốt đẹp toString()cho lớp học của bạn. Điều gì xảy ra nếu lớp đó được đặt vào một mảng hoặc một bộ sưu tập?

Mảng

Nếu bạn có một mảng các đối tượng, bạn có thể gọi Arrays.toString()để tạo ra một biểu diễn đơn giản về nội dung của mảng. Ví dụ, hãy xem xét mảng Personđối tượng này:

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

// Prints: [Fred, Mike]

Lưu ý: đây là một cuộc gọi đến một phương thức tĩnh được gọi toString()trong lớp Mảng, khác với những gì chúng ta đã thảo luận ở trên.

Nếu bạn có một mảng nhiều chiều , bạn có thể sử dụng Arrays.deepToString()để đạt được cùng loại đầu ra.

Bộ sưu tập

Hầu hết các bộ sưu tập sẽ tạo ra một đầu ra đẹp dựa trên việc gọi .toString()trên mọi phần tử.

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

// Prints [Alice, Bob]

Vì vậy, bạn chỉ cần đảm bảo các yếu tố danh sách của bạn xác định một tốt đẹp toString()như được thảo luận ở trên.


return String.format( getClass().getSimpleName() + "[ name=%s ]", name);và thực sự thay vì namesử dụng getter getName()(nhưng getters đã bị bỏ qua trong lớp Person ...) nhưng nếu một getter được sử dụng ...return String.format( getClass().getSimpleName() + "[ name=%s ]", getName());
CrandellWS

Nếu tôi có hai lớp trong tệp java thì làm thế nào để tạo đối tượng của lớp không công khai A.java lớp công khai A {} lớp B {} ------ C.java lớp công khai C {A a = new A ( ); }
yatinbc

Lưu ý rằng có các phiên bản quá tải Arrays.toString()để bạn có thể sử dụng nó cho các mảng nguyên thủy ( int[], double[]). Cũng Arrays.deepToString()xử lý các mảng đa chiều của nguyên thủy độc đáo.
Ole VV

1
@ MasterJoe2 Không chắc chắn, có lẽ họ nghĩ rằng nó sẽ trông xấu xí khi cố mã hóa các giá trị âm vào chuỗi?
Duncan Jones

55

Tôi nghĩ apache cung cấp một lớp sử dụng tốt hơn cung cấp một hàm để có được chuỗi

ReflectionToStringBuilder.toString(object)

5
Điều này có lợi thế là nó không yêu cầu chỉnh sửa lớp, điều này đôi khi không thể. Tuy nhiên, làm thế nào tôi có thể in đệ quy các đối tượng lồng nhau?
lukas84

35

Mỗi lớp trong Java có toString()phương thức trong nó theo mặc định, được gọi nếu bạn chuyển một số đối tượng của lớp đó sang System.out.println(). Theo mặc định, cuộc gọi này trả về mã băm className @ của đối tượng đó.

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

Bạn có thể ghi đè phương thức toString của một lớp để có đầu ra khác nhau. Xem ví dụ này

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
Đây là một câu trả lời hay và ngắn gọn, nhưng để làm rõ lý do tại sao OP lại nhận [Lcom.foo.Person;@28a418fcđầu ra: đó cũng là đầu ra của toString()phương thức, nhưng là một phương thức được triển khai trong lớp được tạo trong thời gian chạy cho loại Person[], chứ không phải Person(xem stackoverflow.com/a/8546532/1542343 ).
gvlasov

Đầu ra này có nghĩa là gói.Class@Hashcode. Phương thức toString () mặc định có kiểu trả về như thế nào. return Object.hasCode () hoặc một số câu lệnh return tương tự đang trả về mã băm ở dạng thập lục phân cùng với tên lớp.
Pankaj Manali

14

Trong Eclipse, Chuyển đến lớp của bạn, Nhấp chuột phải-> nguồn-> Tạo toString();

Nó sẽ ghi đè toString()phương thức và sẽ in đối tượng của lớp đó.


10

Tôi thích sử dụng một hàm tiện ích sử dụng GSON để khử tuần tự hóa đối tượng Java thành chuỗi 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);
    }
}

Nó nên return Gson.toJson(object);, nếu không làm việc hoàn hảo.
Nakrule

Chỉ có vậy thôi.
Agam

5

Trong intellij, bạn có thể tự động tạo phương thức toString bằng cách nhấn alt + inset và sau đó chọn toString () ở đây là một đặt ra cho một lớp kiểm tra:

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 +
            '}';
 }
}

Như bạn có thể thấy, nó tạo ra một Chuỗi bằng cách ghép, một số thuộc tính của lớp, đối với các nguyên hàm, nó sẽ in các giá trị của chúng và cho các kiểu tham chiếu, nó sẽ sử dụng kiểu lớp của chúng (trong trường hợp này là phương thức chuỗi của Test2).


4

Theo mặc định, mọi đối tượng trong Java đều có toString()phương thức xuất ra ObjectType @ HashCode.

Nếu bạn muốn biết thêm thông tin đầy ý nghĩa thì bạn cần ghi đè toString()phương thức trong lớp.

public class Person {
  private String name;

  // constructor and getter/setter omitted

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

Bây giờ khi bạn in đối tượng người sử dụng System.out.prtinln(personObj);nó sẽ in tên của người đó thay vì tên lớp và mã băm.

Trong trường hợp thứ hai của bạn khi bạn đang cố in mảng, nó sẽ in [Lcom.foo.Person;@28a418fckiểu Array và đó là mã băm.


Nếu bạn muốn in tên người, có nhiều cách.

Bạn có thể viết chức năng của riêng bạn lặp đi lặp lại mỗi người và in

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

Bạn có thể in nó bằng Arrays.toString (). Điều này có vẻ đơn giản nhất với tôi.

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

Bạn có thể in nó theo cách java 8 (sử dụng luồng và tham chiếu phương thức).

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

Có thể có những cách khác là tốt. Hi vọng điêu nay co ich. :)


3

Nếu bạn in trực tiếp bất kỳ đối tượng nào của Người thì nó sẽ ClassName@HashCodethành Mã.

trong trường hợp của bạn com.foo.Person@2f92e0f4đang được in. Trường hợp Personmột lớp mà đối tượng thuộc về và 2f92e0f4là hashCode của Object.

public class Person {
  private String name;

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

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

Bây giờ nếu bạn cố gắng sử dụng đối tượng Personthì nó sẽ in tên

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

2

Nếu bạn nhìn vào lớp Object (lớp Parent của tất cả các lớp trong Java) thì việc triển khai phương thức toString () là

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

Bất cứ khi nào bạn in bất kỳ đối tượng nào trong Java thì toString () sẽ được gọi. Bây giờ tùy thuộc vào bạn nếu bạn ghi đè lênString () thì phương thức của bạn sẽ gọi các cuộc gọi phương thức lớp Object khác.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.