JavaのtoStringメソッドとは?文字列に変換したい時のtoStringの使い方【valueOfとの違いも解説】
toStringメソッドは文字列に変換する際に使用するメソッドです。
数値型やオブジェクトの中身を文字列として取得することができます。
ただし自作クラスのオブジェクトの場合、中身を意図した文字列として取得するにはオーバーライドする必要があります。
そんなtoStringメソッドですが、実はJavaを学ぶ中で初期の段階から知らず知らずのうちにお世話になっているメソッドですべてのJavaエンジニアにとってなじみ深いメソッドなんです。
目次
1.toStringメソッドとは
1-1.lang.Objectクラスで定義されているメソッド
toStringメソッドはObjectクラスで定義されているメソッドです。APIには以下のように記載されています。
JavaではすべてのクラスがObjectクラスを継承していますので、どのクラスでもtoStringメソッドを使うことが可能です。
1-2.文字列に変換するためのメソッド
APIにも書かれている通り、toStringメソッドはオブジェクトをテキストで表すための文字列を返すメソッドです。
たとえばオブジェクトを引数にしたSystem.out.printメソッドでは内部でString.valueOfメソッドが呼び出されています。このvalueOfメソッドで引数の型に応じたtoStringメソッドが呼び出されることで文字列が出力される仕組みになっています。
冒頭で知らずのうちにお世話になっているなじみ深いメソッドといったのはまさにこの点で、toStringメソッドを使うことで様々な型のクラスを文字列として取得することができるのです。
1-3.int型をtoStringメソッドでString型に変換しよう
では、ここからは具体的にtoStringメソッドの使い方を見ていきましょう。まずはプリミティブ型の中でも数値型の代表としてint型を例にします。(他のプリミティブ型も基本的な使い方は共通です)
int num1 = 123; int num2 = 456; System.out.println(num1 + num2); String strNum1 = Integer.toString(num1); String strNum2 = Integer.toString(num2); System.out.println(strNum1 + strNum2);
上記のコードの結果は、
---
579
123456
---
となります。
num1とnum2はint型の変数なのでprintlnメソッドの引数で+演算子を使用した場合は値同士の足し算が行われます。対してstrNum1とstrNum2の中身はIntegerクラスのtoStringメソッドでint型のnum1とnum2をString型に変換したものです。この場合printlnメソッドでは引数がString型同士のため文字列連結されます。
ここでのポイントはint型はプリミティブ型のためそのままではメソッドを使うことができません。toStringメソッドでString型に変換するにはラッパークラスであるIntegerクラスからメソッドを呼び出す必要があります。
以上がtoStringメソッドを使ったint型のString型への変換方法です。
※System.out.printメソッドでプリミティブ型を引数にした場合もラッパークラスのtoStringメソッドを経て出力されています。(+演算子による評価はメソッド実行前のため、先にint型として足し算されます)ラッパークラスはプリミティブ型を参照型として扱うためのクラスです。他のプリミティブ型にもそれぞれラッパークラスが用意されているので、気になる方は調べてみてください。
2.自作クラスのtoStringメソッドはオーバーライドしよう
次に、自作クラスでtoStringメソッドを意図して使うにはオーバーライドをする必要がある、ということを見ていきましょう。
package example; public class Dog { String name; int age; String kind; public Dog() { this.name = "ポチ"; this.age = 3; this.kind = "チワワ"; } }
上記のような自作クラスを用意して、mainメソッドで以下を実行します。
Dog dog = new Dog(); System.out.println(dog);
結果は以下です。
---
example.Dog@48140564
---
Dogクラスを文字列で出力したいのに、一見して意味のわからない結果が出力されました。ここで、1-1で紹介したObjectクラスのAPIで定義されているtoStringメソッドの内容を思い出してください。注目するのは以下の部分です。
クラスObjectのtoStringメソッドは、オブジェクトがインスタンスになっている元のクラスの名前、アットマーク文字「@」、およびオブジェクトのハッシュ・コードの符号なし16進数表現から構成される文字列を返します。 つまり、このメソッドは次の値と等しい文字列を返します。
getClass().getName() + ‘@’ + Integer.toHexString(hashCode())
つまり自作クラスでtoStringメソッドが呼び出されるときにオーバーライドしていない場合は継承元であるObjectクラスのtoStringメソッドが呼び出されるため、意図しない文字列が出力されてしまうのです。APIに「このメソッドをオーバーライドすることをお勧めします。」と書かれているのはこのためです。
自作クラスでtoStringメソッドを使用して意図した文字列を出力したいのなら、きちんとオーバーライドして出力したい内容を実装する必要があるよ、そうでなきゃとりあえずObjectクラスで定義している内容で出力しとくね、ということです。
それでは、先ほどのDogクラスでtoStringクラスをオーバーライドしてみましょう。Dogクラスに以下のコードを追加します。
@Override public String toString() { return "Dog [name=" + name + ", age=" + age + ", kind=" + kind + "]"; }
そして、再びmainメソッドで以下を実行します。
Dog dog = new Dog(); System.out.println(dog);
すると結果は以下となります。
---
Dog [name=ポチ, age=3, kind=チワワ]
---
Dogクラスで定義したtoStringメソッドの内容が出力されました。このように自作クラスではtoStringメソッドをオーバーライドすることで意図した文字列を出力できることがおわかりいただけたかと思います。オーバーライドについて詳しく知りたい方は以下の記事を参考にしてみてください。
関連記事3.toStringメソッドの注意点、valueOfメソッドとの違い
toStringを使用する上での注意点としては、nullのオブジェクトを変換しようとするとNullPointerExceptionが発生してしまうことが挙げられます。nullチェックを行うかnullでないことが保証できる状態から呼び出すようにしましょう。
具体的に見てみましょう。
Dog dog = null; System.out.println(dog); String strDog = dog.toString(); System.out.println(strDog);
結果は以下です。
---
null
Exception in thread “main” java.lang.NullPointerException
at sample/example.Main.main(Main.java:9)
---
行数がないのでわかりにくいですが、最初のprintlnメソッドではnullが出力され次の行のtoStringメソッドの呼び出しでNullPointerExceptionが発生しています。(2回目のprintlnメソッドは実行されない)
ここで注目したいのは、NullPointerExceptionが発生するのは、
System.out.println(dog);
ではなく、
String strDog = dog.toString();
であるという点です。
ここで「printlnメソッドは内部でtoStringメソッドが呼び出されているはずでは?」と思った方は鋭いです!
1-2でprintメソッドやprintlnメソッドでは内部でString.valueOfメソッドが呼び出され、valueOfメソッドからtoStringメソッドを呼び出すといいました。実はString.valueOfメソッドではオブジェクトがnullかどうかを判定し、nullの場合は文字列の”null”、そうでない場合はtoStringメソッドを呼び出すようになっています。そのためSystem.out.println(dog);の行ではそもそもtoStringメソッドは呼び出されていないのです。
String.valueOfメソッドも様々な型をString型に変換することができます。toStringメソッドと用途は似ていますが両者ではnullに対する動作の違いがあることを覚えておいてください。
4.まとめ
toStringメソッドの使い方がわかれば自作クラスのオブジェクトの中身を確認することも自在にできるようになります。
仕組みさえ理解してしまえばさほど難しくないのでぜひこの機会に自分のものにしてください。
コメント