質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.01%

toStringメソッドのオーバーライドについて

受付中

回答 3

投稿

  • 評価
  • クリップ 1
  • VIEW 5,100

javaの参考書などをみているとtoStringメソッドをオーバーライドして使っているのがあるのですが、これは何の意味があるのでしょうか?

toStringメソッドは
①Objectクラスに属するメソッド
②インスタンスの内容を文字列表現にして返すメソッド
③クラス名@ハッシュ値」というあまり役に立たない情報しか返さないメソッド
ということはわかりました。

http://www.milk-island.net/document/java/kihon/k3/
を内容を借りています。

コード
public class Dog {

    String name;        //名前
    int cryCount;        //鳴く回数

    /**
     * コンストラクタ。
     * @param name 名前
     * @param cryCount 鳴く回数
     */
    public Dog(String name, int cryCount) {
        this.name = name;
        this.cryCount = cryCount;
    }

}


public class K303 {

    /**メインメソッド。*/
    public static void main(String[] args) {
        // インスタンスを作成
        Dog dog1 = new Dog("クロ", 5);

        // Dogインスタンスの内容を表示
        System.out.println("変数 dog1の参照先インスタンスの内容は " + dog1);
    }

}


この結果は
変数 dog1の参照先インスタンスの内容は toStringメソッド.Dog@1db9742
になります。

コード
public class Dog {

    String name;        //名前
    int cryCount;        //鳴く回数

    /**
     * コンストラクタ。
     * @param name 名前
     * @param cryCount 鳴く回数
     */
    public Dog(String name, int cryCount) {
        this.name = name;
        this.cryCount = cryCount;
    }

    @Override
    public String toString() {
            return "[" + name + ":" + cryCount + "]";
    }

}


public class K303 {

    /**メインメソッド。*/
    public static void main(String[] args) {
        // インスタンスを作成
        Dog dog1 = new Dog("クロ", 5);

        // Dogインスタンスの内容を表示
        System.out.println("変数 dog1の参照先インスタンスの内容は " + dog1);
    }

}


これの結果は
変数 dog1の参照先インスタンスの内容は [クロ:5]
になります。
オーバーライドしているのでこのような結果になるのはわかるのですが、これはなにかメリットがあるのでしょうか?
また、

コード
    public String str() {
            return "[" + name + ":" + cryCount + "]";
    }


    // Dogインスタンスの内容を表示
    System.out.println("変数 dog1の参照先インスタンスの内容は " + dog1.str());

上のようにDogクラスのオーバーライドしたtoStringメソッドをstrメソッドに変えて、K303クラスの("変数 dog1の参照先インスタンスの内容は " + dog1);を("変数 dog1の参照先インスタンスの内容は " + dog1.str());に変更しても同じ結果を得られるのでtoStringメソッドを使わなくてもいいように思います。

toStringメソッドを使う理由、toStringメソッドではいけない理由が何かあるのでしょうか?
toStringメソッドを使う理由、メリットを教えていただきたいです。
よろしくお願いします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

+5

操作の方法を1つにまとめられるというのが大きなメリットです。
オーバーライドせず、めいめいのクラスで好き勝手な文字列化メソッドを実装した場合、

オブジェクトを文字列として出力するにあたり、このオブジェクトはこのメソッドで、あのオブジェクトはあのメソッドで、あれ、それはなんてメソッドだっけ?

ということになり、非常に使い勝手が悪いです。
すべての参照型が持っているtoStringを書き換えたほうが、操作を統一できて便利なのです。

また、独自の文字列化メソッドを実装した場合のデメリットとして、定義したクラスの親クラス型では使えないことも挙げられます。
例のDogクラスの場合、Dog型ならstrメソッドが使えますが、Object型の変数に入った場合に使えなくなります。
ObjectのメソッドtoStringならそんなことはなく、いつでも使うことができます。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/03/27 10:52

    回答ありがとうございます。
    わかりやすい解説ありがとうございます!
    そういう利点があったんですね。

    キャンセル

  • 2017/03/27 10:55

    副次的な効果になりますが、Eclipseではデバッグ画面でオブジェクトの表示がtoStringの結果になるので、デバッグしながら中身がわかるというのもあります。

    キャンセル

+4

toString() メソッドを実装するメリットは、貴方ではなく Dog クラスを利用する他の開発者が享受できるのだ、と考えるとよいでしょう。

インスタンスの文字列表現を得たいと思うことはしばしばあるので、貴方が設計した Dog クラスを利用する私はインスタンス Dog taro; を例えばファイルに出力するために、taro.toString() としたいわけです。

Java の流儀ではインスタンスの文字列表現を取得する場合は Object#toString() を使うと作法が決まっているわけです。決まっていると「私」が助かるわけです。期待した結果が得られず、Dog クラスのドキュメントを読んで str() メソッドを使う必要があることに驚いたりしたくはないのです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/03/27 09:44

    回答ありがとうございます。
    toStringメソッドを使うのが決まっているんですね!
    ちなみにですが、「インスタンスの文字列表現を得たいと思うことはしばしばある」というのは「toStringメソッド.Dog@1db9742」こういう結果が欲しいときがあるということですか?それともインスタンスの引数が欲しいということなのでしょうか?

    キャンセル

  • 2017/03/27 22:06

    > 「toStringメソッド.Dog@1db9742」こういう結果が欲しいときがあるということですか?

    いいえ。
    単純に Dog のインスタンスを例えば Web画面に表示したい、と思ったときに欲しくなる文字列のことを言っています。

    「文字列表現を得たい」という "要件" を表現しているのが、Object#toString() メソッドで、これを継承した Dog クラスで「文字列表現を得る」ための実装を "あなたが" オーバーライドすることを Java の API では想定している。ということです。

    なので、Dogクラスを利用する側も「文字列表現を得るなら Dog#toString() だろう」と考えて使うわけです。

    キャンセル

-2

例えば、以下のように考えて見てはどうでしょう

クラスDogの中身だけ表示したい場合、変数の文字長さを最短の一文字にすると

何と、toString()を用いて表示した場合、str()を用いて表示する場合に対して、System.out.println()内に入力する文字が七分の一で済むのです

str()ではまだ長いからとメソッド名を一文字にしてs()にした場合と比べてすら、System.out.println()内に入力する文字は五分の一で済みます

それらは冗談のようなものだとしても、

あるクラス内のデータを複数回表示したくて何度も何度もその内容を表示するためのコードの入力を繰り返す場合、toString()は入力文字数の合計を自作メソッドを使う場合に対して毎回につき最短(メソッド名がs()など一文字の場合)でも四文字ずつ減らしてくれる実に効率的な仕組みだとは思いませんか・・・
もし、Javaにおける「int」が、四文字も多い「integer」だったとしたら、
毎回毎回int変数を宣言するたびに

integer c=22;
integer d=33;
・・・
と書かねばならなくなりますが、
それよりははるかに今の「int」の方が短くて打ち込みやすく使いやすいとは思いませんか・・・

ましてや上で示されている、「str()」を用いるとしたら毎回につき6文字増えますが、
「int」が六文字多い「intnumber」だったとして、

intnumber a=11;
intnumber  b=22;
・・・
と毎回書かねばならない言語とか地味に辛くはないですか・・・

intは頻繁に使うのに対し、クラスの内容を表示するのはそんなに使わないから多少長くとも構わないように思うかも知れませんが、頻繁に使うと明らかに効率的だと分かってくるものは少しだけ使う場合もやはり同様に効率的なはずです
また、長大なプログラム内で何度もクラス内容を表示する場合は当然この効率化によってかなり全体として打ち込みが楽になるはずです

「寿限無」という、長すぎる名前は最早日常的に使うための用をなさなくなりかねない現実を示す昔の話がありますが、名前が少しでも短くて済む方法があるならそれを使うに越した事はないのではないでしょうか

 class Dog {

    String name;        //名前
    int cryCount;        //鳴く回数

    /**
     * コンストラクタ。
     * @param name 名前
     * @param cryCount 鳴く回数
     */
    public Dog(String name, int cryCount) {
        this.name = name;
        this.cryCount = cryCount;
    }

public String str() {
            return "[" + name + ":" + cryCount + "]";
    }

public String s() {
            return "[" + name + ":" + cryCount + "]";
    }


    @Override
    public String toString() {
            return "[" + name + ":" + cryCount + "]";
    }

}


public class K33 {

    /**メインメソッド。*/
    public static void main(String[] args) {
        // インスタンスを作成
        Dog a = new Dog("クロ", 5);

        // Dogインスタンスの内容を表示
        System.out.println(a);//()内が一文字で済んだ
        System.out.println(a.str());//()内は七文字も必要
        System.out.println(a.s());//()内は五文字必要

    }

}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/03/26 01:48

    文字列連結や出力がtoString()を参照することによる副次的効果にしか見えないです…

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.01%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる