こんにちは。
今日はとても暑いですね。
今から暑いと言っていては夏本番が越せなさそうです。。
さて今日はコンストラクタの呼び出しに関する問題です。
問.次のコードをコンパイル、実行したときの結果として正しいものを選びなさい。
class B extends A{
int b, c;
B(int num){
b = num;
}
B(int num, int num2){
this(num);
c = num2;
}
}
class A {
int a;
A(){ a = 1; }
A(int num){ a = num}
}
public class Main{
public static void main(String[] args){
B b = new B(2, 3);
System.out.println(b.a + "," + b.b + "," + b.c);
}
}
A. 「0,2,3」と表示される
B. 「1,2,3」と表示される
C. 「2,0,3」と表示される
D. 「2,2,3」と表示される
—————–この先答え———————-
答.B
サブクラスのコンストラクタ内でのスーパークラスのコンストラクタ呼び出しに関する問題です。
解説が長くなりますのでご了承ください。。
コンストラクタはインスタンスを利用する前の準備をする特別なメソッドです。
2つのクラスに継承関係が成り立つと、サブクラスのインスタンスを準備するより前に、スーパクラスのインスタンスの準備を整えなければなりません。
そのため、スーパークラスのコンストラクタを実行したあとに、サブクラスのコンストラクタを実行する必要があります。
このようなルールを実現するために、サブクラスのコンストラクタの先頭行では、スーパークラスのコンストラクタ呼び出しをしなければならないことが言語仕様で決められています。
設問コードではMainクラスの3行目で、int型の引数を2つ受けるコンストラクタを使ってBクラスのインスタンスを生成しています。
このコンストラクタではではthisを使ってオーバーロードされた別のコンストラクタを呼び出しています。
サブクラスのコンストラクタ内でのスーパークラスのコンストラクタ呼び出しよりも先に何らかの処理を記述することはできませんが、
オーバーロードされた別のコンストラクタの先頭行で、スーパークラスのコンストラクタ呼び出しをする必要があります。
このスーパークラスのコンストラクタ呼び出しコードはプログラマーが明示的に記述しなかった場合、コンパイラが自動的にコードを追加します。
そのため、コンパイル後のコンストラクタの定義は次のようになります。
B(int num){
super(); ←コンパイラによって追加されたコード
b = num;
}
B(int num, int num2){
this(num);
c = num2;
}
BクラスのスーパークラスであるAクラスの引数なしコンストラクタでは、変数aに1を代入してきます。
また、Bクラスのint型の引数を1つだけ受け取るコンストラクタでは変数bに2を、引数を2つ受け取るコンストラクタでは変数cに3を代入していきます。
そのため、コンソールには「1,2,3」が表示されます。なので正解はBになります。
この問題は自分では理解できなかったので教えていただきました。
thisを使ってオーバーロードされた別のコンストラクタを呼び出していることを理解できるかがポイントですね。
落ち着いて考えていけば解けると思います!
しかしテストでは後回しにしてもいい問題ではないかと私は思います。(やっぱり複雑なので。。)