Java: toString()に頼るべきではない

投稿日: 更新日:

何が悩みか

例えば、文字列をValueObjectの考え方で、 オブジェクトとして扱いたい場合があります。 以下のようなコードです。

public class ItemCode {
  private final String itemCode;

  public ItemCode(String itemCode) {
    this.itemCode = itemCode;
  }
}

このようなときに、元のitemCodeを取得したい場合に、 どの方式を選ぶかというのが悩みでした。

  1. toString()
  2. getItemCode(), itemCode()のようなゲッター
  3. format(formatter)

結論としては、3>2>1の順でよく、ログ以外では1は避けるべきという認識です。

理由

フォーマット指定が柔軟

まず、3.の方式がいい理由は、柔軟に対応できるからです。

例えば、java.timeに含まれているクラスの多くには、formatメソッドがあります。

これに限らず必要な文字列表現は1つとは限らないため、書式を指定できるといいでしょう。

呼び出し元を見つけるのに苦労する

次に、ゲッターよりtoString()の方がよくない理由です。 それは、呼び出し元をIDEで見つけられないからです。

Eclipseでは(Oxygenで確認)オーバーライドされたメソッドの呼び出しを、 元のメソッド呼び出しと区別して検索できません。 なので、toString()の呼び出し元を調べると、 Object#toString()の呼び出しがずらっと表示されます。

IntelliJ IDEAはObject#toString()の呼び出しなのか、 オーバーライドされたメソッドのみの呼び出しなのか、明示的に指定して検索できます。

しかし、"object: " + obj のような、toString()の暗黙的呼び出しについては、 IntelliJ IDEAでも対応できません。

なので、toString()を使うと、変更が必要なときの影響調査で死にます。 ログだけに使うのが賢明です。

toString()の実装方法

toStringはCommons LangのToStringBuilderクラスを用いて、 自オブジェクトの中身を表示するのが最も分かりやすいと思います。

toString()は形式を明示しないと書く

Effective Javaの「項目10 toStringを常にオーバーライドする」には、 以下のように書かれています。

もし、形式を明示しないと決めたのであれば、 ドキュメンテーションコメントは、次のように書かれるべきです。

その後にJavadocコメントの例がありますが、 「変更されることがあります」と書いておけばよいかと思います。

辞書

  • Java
  • string: まだありません。