toString()とは
java.lang.Objectに実装されているメソッドで、すべてのクラスでオーバーライド可能なメソッドです。そのインスタンスの文字列表現を返すメソッドなのですが、特にオーバーライドしていない場合デフォルトメソッド(Objectクラスに実装されているtoString)が呼ばれます。
toString()をオーバーライドしていないことによる問題
以下のような構成でtoStringをオーバーライドせず、Objectクラスに実装されているtoStringでEmployeeインスタンスの文字列表現を返すとします。
package co.jp.arsware;
public class Employee {
private String id;
private String name;
public Employee(String id, String name) {
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package co.jp.arsware;
public class Main {
public static void main(String[] args) {
Employee nagaoka = new Employee("001", "Nagaoka");
System.out.println(nagaoka);
}
}
結果は以下の通りです。
co.jp.arsware.Employee@15db9742
ここで期待するのは、idやnameにどんな値が設定されているのかがほとんどだと思うのですが、これではなんのことか分かりませんよね。基本的にObjectクラスのtoStringが返す結果にはそのクラスを利用するユーザーが見たい情報は存在しません。
toString()をオーバーライドして自身の情報を親切に伝える
次に、Employeeクラスに以下の通りtoStringをオーバーライドして、再度Mainメソッドを実行してみます。
~省略~
@Override
public String toString() {
return "id=" + this.getId() + ", name=" + this.getName();
}
結果は以下の通りです。先ほどの出力に比べてより有用な情報が出力されていることがわかります。
id=001, name=Nagaoka
しかし、これはこれでtoStringのオーバーライド実装工数がかかります。そのため、LombokのToStringアノテーション等のような、ボイラープレートコードを自動生成してくれるライブラリを導入することで、冗長なコードを書くという工数を削減することができます。
教訓
優れたtoStringの実装を提供することでそのクラスが使いやすくなり、そのクラスを使っているシステムをデバッグしやすくなります。println、printf、文字列結合演算子(+)、assert等のメソッドにインスタンスが渡されたり、デバッガによりインスタンスが表示されたりすると、toStringが自動的に呼び出されます。つまり、toStringを自分では呼び出さないとしても、他の誰かが呼び出す可能性があります。例えば、そのインスタンスの内容をそのままログ出力するケース等がそれにあたるかと思います。そういったケースも考慮して、可能な限りtoStringはオーバーライドして自身の情報を親切に伝えることを意識すると良いかと思います。