HOWTO · Java

Java で toString メソッドをオーバーライドする

この記事では、Java で toString()メソッドをオーバーライドする方法について説明します。

このページの内容

Java でオブジェクトを出力すると、そのオブジェクトの toString() メソッドが呼び出され、文字列が取得されます。継承した既定の実装は通常、オブジェクトのクラスとハッシュ値に基づく値を示します。インスタンスの区別には役立つことがありますが、内容を説明するものではありません。toString() をオーバーライドすると、ログ、デバッグ、通常の出力で役立つ簡潔な表現を用意できます。

toString() の既定の出力が示すもの

Java の各クラスは、スーパークラスまたはそのクラス自体でオーバーライドされていない限り、Object から toString() を継承します。System.out.println(book) のような呼び出しでは、オブジェクトの文字列表現が使われます。この呼び出しは暗黙に行われるため、自分で book.toString() と書く必要はありません。

既定の表現は、安定した識別子でも、オブジェクトのフィールドを示す保証でもありません。ハッシュ値に基づく部分は実行ごとに変わることがあり、オブジェクトの状態を読み取れる形で示すものでもありません。既定の出力例をアプリケーションのロジックやテストにそのまま使うのは避けてください。クラスにより分かりやすい文字列表現を持たせたい場合は、独自の実装でオーバーライドします。

toString() を @Override でオーバーライドする

public String toString() という正確なシグネチャを持つ public メソッドを宣言し、String を返します。@Override アノテーションは、このメソッドが継承したメソッドを置き換える意図であることをコンパイラーに伝えます。また、名前の入力ミスや誤った引数リストの検出にも役立ちます。次の完全な例では、本のタイトルと著者を保持し、それらのフィールドから文字列表現を組み立てます。

この例を実行します。

このセクションのコードと表示されるラベルや出力は英語のままです。

public class BookExample {
    public static void main(String[] args) {
        Book book = new Book("Dune", "Frank Herbert");
        System.out.println(book);
    }
}

class Book {
    private final String title;
    private final String author;

    Book(String title, String author) {
        this.title = title;
        this.author = author;
    }

    @Override
    public String toString() {
        return "Book{title='" + title + "', author='" + author + "'}";
    }
}

例をコンパイルして実行する

public クラス名が BookExample なので、ソースを BookExample.java という名前のファイルに保存します。そのディレクトリで javac BookExample.java を実行してコンパイルし、続けて java BookExample を実行します。正常に実行されると、Book.toString() が返す表現である Book{title='Dune', author='Frank Herbert'} が出力されます。

重要なのは、toString() は文字列を返すだけで、それ自体は何も出力しないという点です。System.out.println(book) はその表現を取得してコンソールに書き込みます。返された文字列はロガーや別のメッセージにも使えます。表示やログへの出力方法を決める処理は、メソッドの外に置いてください。

役立つ toString() の出力を選ぶ

オブジェクトを見分け、現在の状態を理解するのに役立つフィールドを含めます。形式は簡潔にし、分かりやすくなる場合は値にラベルを付け、パスワードやアクセストークンなどの秘密情報は含めないでください。この表現は人が読むためのものです。継承したハッシュ値に基づく文字列に頼らず、安定していて理解しやすい値を選びます。

このメソッドでは状態を表現し、関係のない処理は行わないようにします。文字列の組み立て中にフィールドを変更したり、メッセージを出力したり、時間のかかる処理を行ったりするのは避けてください。フィールドが多いクラスでは、扱いにくいほど大量の情報を返すのではなく、診断に役立つものを選びます。公開ファイルやネットワークプロトコルで厳密な書式が必要なら、その書式を別途定義してテストしてください。呼び出し側がデバッグ用の表現をデータ形式として解析しなくて済むようにします。