Java toString()

toString() 方法用於回傳物件的字串表示,覆寫此方法可以提供有意義的輸出。

預設行為

public class Person {
    private String name = "Alice";
}

Person p = new Person();
System.out.println(p.toString());  // Person@6d06d69c
System.out.println(p);             // 同上,println 會自動呼叫 toString

預設格式:類別名稱@十六進位hashCode

覆寫 toString()

public class Person {
    private String name;
    private int age;
    
    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + "}";
    }
}

Person p = new Person("Alice", 25);
System.out.println(p);  // Person{name='Alice', age=25}

常見格式

簡單格式

@Override
public String toString() {
    return name + " (" + age + ")";
}
// Alice (25)

類名加欄位

@Override
public String toString() {
    return "Person{" +
           "name='" + name + '\'' +
           ", age=" + age +
           ", email='" + email + '\'' +
           '}';
}
// Person{name='Alice', age=25, email='alice@example.com'}

使用 String.format

@Override
public String toString() {
    return String.format("Person[name=%s, age=%d]", name, age);
}
// Person[name=Alice, age=25]

使用 StringBuilder

@Override
public String toString() {
    return new StringBuilder()
        .append("Person{")
        .append("name='").append(name).append('\'')
        .append(", age=").append(age)
        .append('}')
        .toString();
}

使用 StringJoiner

@Override
public String toString() {
    return new StringJoiner(", ", Person.class.getSimpleName() + "[", "]")
        .add("name='" + name + "'")
        .add("age=" + age)
        .toString();
}
// Person[name='Alice', age=25]

Record 自動實作

public record Person(String name, int age) {}

Person p = new Person("Alice", 25);
System.out.println(p);  // Person[name=Alice, age=25]

Arrays.toString

陣列的 toString 需要特殊處理:

int[] arr = {1, 2, 3};
System.out.println(arr);                  // [I@6d06d69c(無意義)
System.out.println(Arrays.toString(arr)); // [1, 2, 3]

int[][] arr2d = {{1, 2}, {3, 4}};
System.out.println(Arrays.deepToString(arr2d)); // [[1, 2], [3, 4]]

集合的 toString

List<String> list = Arrays.asList("A", "B", "C");
System.out.println(list);  // [A, B, C]

Map<String, Integer> map = Map.of("a", 1, "b", 2);
System.out.println(map);  // {a=1, b=2}

最佳實踐

包含所有重要欄位

@Override
public String toString() {
    return "Order{" +
           "id=" + id +
           ", customer='" + customer + '\'' +
           ", total=" + total +
           ", status=" + status +
           '}';
}

處理敏感資料

@Override
public String toString() {
    return "User{" +
           "username='" + username + '\'' +
           ", password='***'" +  // 隱藏密碼
           ", email='" + email + '\'' +
           '}';
}

處理 null

@Override
public String toString() {
    return "Person{" +
           "name='" + (name != null ? name : "N/A") + '\'' +
           ", age=" + age +
           '}';
}

處理循環參考

public class Node {
    private String value;
    private Node next;
    
    @Override
    public String toString() {
        return "Node{" +
               "value='" + value + '\'' +
               ", next=" + (next != null ? "Node@" + System.identityHashCode(next) : "null") +
               '}';
    }
}

偵錯用途

public void process(Order order) {
    logger.debug("Processing order: {}", order);  // 自動呼叫 toString
    // ...
}

重點整理

  • 覆寫 toString() 提供有意義的字串表示
  • 包含類別名稱和重要欄位
  • 隱藏敏感資訊(如密碼)
  • 陣列使用 Arrays.toString()
  • Record 自動實作 toString()
  • 有助於偵錯和日誌記錄