クラスもメモリを使う
突然ですが問題です。次のプログラムは何が表示されるでしょうか。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
package jp.ayax.object; public class Main { public static void main(String[] args) { // TODO 自動生成されたメソッド・スタブ Test abc = new Test(); Test def = new Test(); abc.setNum(4); def.setNum(6); System.out.println(abc.getNum()); } } class Test { int num; public int getNum(){ return num; } public void setNum(int num){ this.num = num; } } |
答えは「4」です。当たり前だと思われる人も多いかと思いますが、より複雑なクラスを理解するには重要なところです。動きを確認していきましょう。
7行目でクラスTestが「new」されるとクラスがメモリに展開され、「abc」という名前が付けられるとイメージしてください。
7 |
Test abc = new Test(); |
8行目でさらにクラスTestが「new」されるとメモリに展開され、「def」という名前が付けられます。
8 |
Test def = new Test(); |
つまり同じクラスTestですが「new」されるたびに別のメモリに展開され別の名前が付きます。そのためメソッドsetNumで変数numに値を設定すると、abc、defそれぞれ別の値を保持できるのです。
継承した場合
次のようにクラスTest2がクラスBaseを継承している場合はどのようにメモリに展開されるのでしょうか。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
package jp.ayax.object; public class Main2 { public static void main(String[] args) { // TODO 自動生成されたメソッド・スタブ Test2 abc = new Test2(); abc.process1(); } } class Base{ public void process1(){ System.out.println("Base:process1"); } public void process2(){ System.out.println("Base:process2"); } } class Test2 extends Base{ public void process1(){ System.out.println("Test:process2"); super.process1(); } public void process3(){ System.out.println("Test:process3"); } } |
継承元クラス(スーパークラス)も継承クラス(サブクラス)もメモリに展開されます。
21行目~24行目のようにサブクラスでメソッドをオーバーライドしている場合は、オーバライドしているメソッドが優先的に実行されます。
21 22 23 24 |
public void process1(){ System.out.println("Test:process2"); super.process1(); } |
スーパークラスはメモリに展開されると「super」という名前が付きます。スーパークラスにアクセスしたい時には、23行目のように「super.」を付けてます。
23 |
super.process1(); |
理解しずらいクラスの構造に出会うことがあります。その時には、どのようにメモリに展開されるかイメージすると解決することがありますので、是非試してみてください。