総まとめ試験用の類似問題を演習する。
内容をよく理解し、類題を解けるように練習しておくこと。
次のプログラムをクラス Exercise1 の main から実行したとき表示される結果を、パソコンを使わず自分で動作を考えて、示しなさい。
public class Exercise1 {
public static void main(String[] args) {
Aa x = new Aa();
// ①
x.countUp12();
// ②
x.countUp();
// ③
System.out.println( "count1=" + x.getCount1()
+ " count2=" + x.getCount2()
+ " count3=" + x.getCount3() );
Bb y = new Aa();
// ④
y.countUp12();
// ⑤
y.countUp();
// ⑥
System.out.println( "count1=" + y.getCount1()
+ " count2=" + y.getCount2() );
}
}
class Aa extends Bb {
static int count3 = 7;
private String s = "Class Aa";
Aa() { System.out.println( s ); }
static void countUp() { count3 += 10; }
void countUp12() {
count1 += 17;
count2 += 17;
}
static int getCount3() { return count3; }
}
class Bb {
static int count1;
int count2 = count1 + 5;
private String s = "Class Bb";
Bb() { System.out.println( s ); }
void countUp12() {
count1 += 13;
count2 += 13;
}
static void countUp() { count1 += 3; }
static int getCount1() { return count1; }
int getCount2() { return count2; }
}
上のコードをコピー&ペーストし、Exercise1.java の名前で保存し、コンパイル・実行して出力を確かめなさい。
出力は以下のようになるはずである。
クラス Exercise1 はメインとして実行されるクラスで、その中でクラス Aa, Bb を利用している。両クラスを分析する必要がある。以下のように、フィールドおよびメソッドをstaticかどうかで区別して列挙しておく。
●クラス Aa
| インスタンス フィールド(変数) | s |
|---|---|
| staticフィールド(変数) | count3 |
| インスタンス メソッド | countUp12 |
| staticメソッド | countUp |
| getCount3 |
●クラス Bb
| インスタンス フィールド(変数) | count2 |
|---|---|
| s | |
| staticフィールド(変数) | count1 |
| インスタンス メソッド | countUp12 |
| getCount2 | |
| staticメソッド | countUp |
| getCount1 |
動作を考える際、基本として把握しておくべきことがある。
上記コードでは、staticメソッドがインスタンス変数を介して呼び出されるかのように記述されている。Java では文法的に許されてはいるが推奨されない記述法である。
しかし実際には、staticメソッドはインスタンスには無関係でクラスに結びついている。
実用的なコードでは、staticメソッド呼び出しは、下記の赤色部分のように、クラスを明示して呼び出すべきである。
public class Exercise1 {
public static void main(String[] args) {
Aa x = new Aa();
x.countUp12();
Aa.countUp(); // x.countUp では、x が Aa 型として宣言されているので
System.out.println( "count1=" + Bb.getCount1() // x.getCount1 では、Aa には getCount1 がなく、スーパークラスの Bb に getCount1 があるので
+ " count2=" + x.getCount2()
+ " count3=" + Aa.getCount3() ); // x.getCount3 書き換え
Bb y = new Aa();
y.countUp12();
Bb.countUp(); // y.countUp では、y が Bb 型として宣言されているので
System.out.println( "count1=" + Bb.getCount1() // y.getCount1 書き換え
+ " count2=" + y.getCount2() );
}
}
プログラムの詳細動作を説明する図は下のようになる。ソースコード上の①~⑥に来る直前に設定される変数の変化を矢印で示している。
なお、static変数の初期化について補足しておく。
①の直前行でクラス Aa およびそのスーパークラスであるクラス Bb が初めて使用されるため、①の直前行のコードを実行する前に、クラス Bb の初期化およびクラス Aa の初期化が順に実行される。すなわち、クラス Bb およびクラス Aa の static 変数の値設定がこの時行われる。
その結果、クラス Bb の count1 は 0、クラス Aa の count3 は 7 に値設定される。

次のプログラムをクラス Exercise2 の main から実行したとき表示される結果を示しなさい。
演習17でやったのと同様に、クラス Ak, Bk のフィールドおよびメソッドをstaticの有無で区別して列挙しなさい。
●クラス Ak
| インスタンス フィールド(変数) | |
|---|---|
| staticフィールド(変数) | |
| インスタンス メソッド | |
| staticメソッド | |
●クラス Bk
| インスタンス フィールド(変数) | |
|---|---|
| staticフィールド(変数) | |
| インスタンス メソッド | |
| staticメソッド | |
自分で結果を考えた後、実際にプログラムを作成・実行し、出力を確かめなさい。
その出力結果を説明できるよう、演習17で示したのと同様な、プログラム動作の詳細説明図を作りなさい。ソースコード上の①~⑥に来る直前に設定される変数の変化を矢印で示すこと。