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

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

ただいまの
回答率

88.23%

コンストラクタのオーバーロードについて

解決済

回答 5

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 3,310

javacurry

score 52

コンストラクタのthis();の動きが理解できないので小さいプログラムでいろいろテストしてみたのですが、いまいち理解ができません。呼び出されるコンストラクタはインスタンスを生成するときの引数の種類と数に応じて自動で判断されているという部分とthis();はコンストラクタに同じ記述をしないで済むというメリットの2点は理解できます。そこで質問です。結果は下です。

  1. 例えばA a = new A(100);でインスタンスを生成したときのプログラムは具体的にどう動いているのでしょうか?結果を見ても考えていた動きと違うので混乱しています。
  2. コンストラクタが複数ある場合this();はどういう基準で別のコンストラクタを呼び出しているのでしょうか?他2つのどちらが呼ばれているのかわかりませんでした。
  3. みなさんはどういう場面でthis();を使おうと考えるのでしょうか?

数時間this();の動きに頭を悩ませています。アドバイスをいただけるとうれしいです。

【追記】
koko_uさんからの追記依頼がありましたので追記いたします。

元々はインスタンスを生成するときに引数を100と指定したのでpublic A(int i)が呼び出されてthis("s");がどういう動きをするのだろうかと勉強のために作ったプログラムでした。

100
s
7


おそらく上記のような表示だろうと考えていたのですが100の表示順どころか3つ目にもsが表示されてしまったところが「考えていた動きと違う」という点です。

public class A {
    private String s;
    private int i;

    public A(String s, int i) {
        this.s = s;
        this.i = i;
        System.out.println(s);
        System.out.println(i);
    }

    public A(String s) {
        this(s, 7);
        System.out.println(s);
    }

    public A(int i) {
        this("s");
        System.out.println(i);
    }
}

public class Main {
    public static void main(String[] args) {
        A a = new A(100);
    }
}
s
7
s
100
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • koko_u

    2017/05/21 22:07

    すでにたくさん回答がついてますが、質問者さんの「考えていた動き」がわからないので回答は控えます。

    キャンセル

  • javacurry

    2017/05/21 23:40

    「考えていた動き」を追記しました。

    キャンセル

回答 5

checkベストアンサー

+3

コンストラクタが複数ある場合this();はどういう基準で別のコンストラクタを呼び出しているのでしょうか?他2つのどちらが呼ばれているのかわかりませんでした。

  1. mainメソッドにおいてnew A(100)
    引数がint型1つなので、int型1つを引数にとるpublic A(int i)が呼び出される
  2. public A(int i)の1行目においてthis("s")
    引数がString型1つなので、String型1つを引数にとるpublic A(String s)が呼び出される
  3. public A(String s)の1行目においてthis(s, 7)
    sはString型の変数、そして7はint型なので、public A(String s, int i)が呼び出される
  4. public A(String s, int i)の処理中、sとiの出力→"s"と"7"が出力される(1行目と2行目)
  5. ここでpublic A(String s)の中のthis(s, 7)の処理が終了し、その次の行でsを出力→"s"が出力される(3行目)
  6. ここでpublic A(int i)の中のthis("s")の処理が終了し、次の行でiを出力→100が出力される(4行目)

と、これだけの話なのですが…

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/05/21 23:26

    >public A(String s)の1行目においてthis(s, 7)
    >sはString型の変数、そして7はint型なので、public A(String s, int i)が呼び出される

    これですとsと7の2つが表示されて終わりますが実行してみると更にsと100が表示されます。100は引数で指定したので表示される予想はしていたのですが、なぜ3つ目のsが表示されるのかがわかりません。

    キャンセル

  • 2017/05/21 23:42

    自クラスのほかのコンストラクタを呼び出しただけで、最初に呼び出したコンストラクタの処理はまだ途中です。メソッド処理中にほかのメソッドを呼び出して、終わったら元の場所に戻って処理を続行するのと全く同じです。

    キャンセル

  • 2017/05/22 17:42

    おかげさまでメソッドの処理中の動きが少しわかりました。アドバイスありがとうございました!

    キャンセル

+2

A1    public A(String s, int i) 
A2    public A(String s) 
A3    public A(int i) 

と便宜的に記述します。

Mainメソッドの中でA3が呼び出されます。
A3の中
{
→A2が呼び出されます。
→→2の中
→→{
→→→A1が呼び出されます。
→→→→A1の中
→→→→{
→→→→→→→文字列"s"が出力されます。
→→→→→→→数字7が出力されます。
→→→→}
→→→文字列"s"が出力されます。
→→}
→数字100が出力されます。
}

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/05/21 23:23

    3つ目がなぜ文字列sなのかがわからないのですが、もしかして→のインデントが関係しているのでしょうか?

    キャンセル

+2

new A(100);
→ public A(int i)
→ this("s") → public A(String s)
→ this(s, 7) → public A(String s, int i)
→ System.out.println(s) ... "s"を出力
→ System.out.println(i) ... 7を出力
→ A(String s) に戻って System.out.println(s) ... "s"を出力
→ A(int i) に戻って System.out.println(i) ... 100を出力

となっているように書かれていますが、どこに疑問を感じますか?

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/05/21 23:18

    → System.out.println(i) ... 7を出力
    → A(String s) に戻って System.out.println(s) ... "s"を出力

    int型の引数でインスタンスを生成したのでA(int i)から始まり、そのメソッドのなかの最初の行のthis("s")はString型なので次に・・という行きの流れはわかったのですが、なぜA(String s)に戻るのかがわかりません。

    キャンセル

+2

1.についてはHogeAnimalLoverさんが回答されているので・・・

  • コンストラクタが複数ある場合this();はどういう基準で別のコンストラクタを呼び出しているのでしょうか?
    コンストラクターでもメソッドでもオーバーロードしているもののどれが選択されるかの規則は同じです。呼び出しの際の実引数の型と個数によってどれになるかが決まります。型は正確に一致してなくても暗黙変換により「一番適合するもの」が選択されます。このあたりは中途半端に考えてもあまり益はないので教科書か言語仕様書で「完全で正確な定義」を参照することをお勧めします。

  • どういう場面でthis();を使おうと考えるのでしょうか? 
    コンストラクターの引数のバリエーションを持たせたい場合に使います。質問者さんのコードでやっていることと同様ですね。バリエーションを持たせたい理由は「一部の引数を省略したい」ことが多いと思います。残念ながらJavaではデフォルト値を与えることで引数を省略するといったテクニックが言語仕様上サポートされてないため、コンストラクターの引数のバリエーションを作りたいと思ったらオーバーロードするしかありません。しかしオーバーロードした各メソッドの実装を同じように書くのはナンセンスですので、あるコンストラクターは「そのコンストラクターより引数の数が多い別のコンストラクター」を呼び出すようにするのが一般的によく使われるケースだと思います。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/05/21 23:19

    規則は一緒なんですね。少しずつわかってきました。

    キャンセル

+1

2に関してですが、引数として受け取れないものは呼び出されません。受け取れる物は次の優先順位になっています。

型が同じ>暗黙的に型変換されるもの>ラッパークラス>可変長引数

例えば、次のコンストラクタがあります。

A (int a) {}  // 型が同じ
A (double a) {} // 暗黙的に型変換されるもの
A (Integer a) {} // ラッパークラス
A (String a) {} // A(100)では呼び出されないもの


これらに対してA(100)で呼び出しを行なった場合、A (int a)が呼び出されます。
A (int a)をコメントアウトした場合、A (double a)が呼び出されます。
A (double a)をコメントアウトした場合、A (Integer a)が呼び出されます。
A (Integer a)をコメントアウトした場合、コンパイルエラーになります。
A (String a)の引数はStringであり、100を入れることができないからです。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/05/21 23:20

    優先順位があったんですね。アドバイスありがとうございます。

    キャンセル

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

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

関連した質問

同じタグがついた質問を見る