JPIN#6 part1
コンストラクタとカプセル化を確認しよう
今回は以下に提示したコードがどのように動いていくのかを解説していく
まずListクラス
public class List {//Listクラス private String value; private int index; private List next; public List() {//公開のListメソッド this.value = null; this.index = 0; this.next = null; } private List(int index) {//非公開のListメソッドはint型を受け取る this();//上記Listメソッドのthisをコピー this.index = index;//このクラスのindexに受け取ったindexを代入 } public void add(String value) {//公開のaddメソッドはString型を受け取る if(this.value == null) {//もしこのクラスのvalueがnullならば以下を実行 this.value = value;//このクラスのvalueに受け取ったvalueを代入 return;//このメソッド終わり } if (this.next == null) {//もしこのクラスのnextがnullだったら以下を実行 this.next = new List(index + 1);//このクラスのnextに新たに作ったListクラスのListメソッドにindex+1を渡したものの参照アドレスを代入する } this.next.add(value);//このクラスのnextに書いてあるアドレスのaddメソッドに受け取ったvalueを代入する } public String get(int index) {//公開のgetメソッドはint型を受け取る if(this.index == index) {//もしこのクラスのindexと受け取ったindexが同じなら以下を実行 return this.value;//このクラスのvalueを返す } if(this.next == null) {//もしこのクラスのnextがnullなら以下を実行 return null;//nullを返す } return this.next.get(index);//このクラスのnextに書かれているgetメソッドに受け取ったindexを代入したものを返す } public int size() {//公開のsizeメソッド if(this.next == null) {//もしこのクラスのnextがnullなら以下を実行 return this.index+1;//このクラスのindexに+1して返す } return this.next.size();//このクラスのnextにあるsizeメソッドを実行して返す }
次にこれを動かすMainクラス
public class Main { public static void main(String[] args) { List list = new List();//Listクラスをヒープ領域にコピーしてlistにアドレスをコピー list.add("A");//listに書いてあるaddメソッドにAを渡して実行 list.add("B");//listに書いてあるaddメソッドにBを渡して実行 list.add("C");//listに書いてあるaddメソッドにCを渡して実行 for (int i = 0; i< list.size(); i++) {//i=0から始まり、listに書いてあるsizeメソッドがiより大きくなるまで以下実行してiに+1 System.out.println(list.get(i));//listに書いてあるgetメソッドにiを渡して出力 } } }
Mainクラスから順に追ってこの二つのコードがどのように動いていっているのかを解説する
まず最初にMainメソッドがスタック領域に乗る
次にListクラスのコピーをヒープ領域に作っている
これが『List list = new List();』の部分だ
このクラスの参照アドレスをlistとしている
次に『list.add("A");』とある
これは先ほど作ったListクラスのaddメソッドにString型の”A”を引数として渡している
ここでListクラスを見てみよう
Listクラスでは最初にprivateで3つの変数が唱えられている
そしてpublicのListメソッドで各値を初期化している
そして引数”A”を受け取ったaddメソッドは実行される
現在、this.valueはnullなのでthis.valueに”A"が代入されてこのメソッドは終了する
Mainメソッドに戻ろう
次に『list.add("B");』では先ほどのListクラスのaddメソッドに今度は"B"を引数として渡している
addメソッドを見ると最初にif文でthis.value ==nullとなっていない(this.value=="A")なので次のif文が実行される
this.next==nullなので『this.next = new List(index + 1);』を実行します
LIstメソッドに引数index+1を渡したもののコピーをヒープ領域に作成して、その参照アドレスをthis.nextに入れます
ここでindex+1を受け取るのはprivateのListメソッドである
privateのListメソッドを実行するとthis.index==1となる
このクラスのアドレスがListクラス①のthis.nextに入った
次に『this.next.add(value);』となっているので
this.next、つまりListクラス②のaddメソッドに引数value("B")を渡す
addメソッドでthis.value==nullなのでthis.valueに”B"が代入されてこのメソッドは終了する
Mainメソッドに戻ろう
『list.add("C");』ではList クラス①のaddメソッドに引数"C"を渡している
上の図でもわかるようにListクラス①のaddメソッドにはA、0、List②のアドレスが書かれているため、
addメソッドの『this.next.add(value);』だけ実行される
Listクラス②のaddメソッドにはB、1、nullが入っているため、『this.next = new List(index + 1);』が実行される
Listクラス②のthis.nextに、Listクラスに引数index+1(ここでindex==1なので、2)を渡したもののコピーをヒープ領域に作りその参照アドレスを記憶する
そしてaddメソッドの『this.next.add(value);』が実行される
Listクラス③はnull、2、nullとなっているのでthis.valueに引数value("C")が代入されてこのメソッドは終了する
Mainメソッドに戻ろう
次にfor文である
『for (int i = 0; i< list.size(); i++)』でListクラス①のsizeメソッドが実行される
Listクラス①のthis.nextはList②のアドレスなので『return this.next.size()』が実行される
Listクラス②のthis.nextはList③のアドレスなので『return this.next.size()』が実行される
Listクラス③のthis.nextはnullなので『return this.index+1;』が実行される
つまりListクラス③のthis.index+1(this.indexは2なので3となる)をして値を返すのである
ここまできてようやくMainメソッドのfor文の条件が0〜3と分かる
※上図のsize(List③)のindexは3に繰り上がりません!2のままです!!誤記です!!)
Mainメソッドのfor文の中を見てみよう
『System.out.println(list.get(i));』となっているのでまずはListクラス①のgetメソッドに引数0を渡そう
ここでListクラス①はA、0、List②となっているのでthis.index==indexとなる
よって『return this.value;』を実行するのでlist.get(0)はAとなる
※上図のsize(List③)のindexは2のままです!!誤記です!!)
次にiは+1されてi==1となり『System.out.println(list.get(i));』を実行
Listクラス①はA、0、List②となっているので『return this.next.get(index);』が実行される
Listクラス②のgetメソッドにindex(1)を渡して実行する
Listクラス②はB、1、List③なのでthis.index==indexとなる
よって『return this.value;』を実行するのでlist.get(1)はBとなる
※上図のsize(List③)のindexは2のままです!!誤記です!!)
次にiは+1されてI==2となり『System.out.println(list.get(i));』を実行
Listクラス①はA、0、List②となっているので『return this.next.get(index);』が実行される
Listクラス②のgetメソッドにindex(2)を渡して実行する
Listクラス②はB、1、List③となっているので『return this.next.get(index);』が実行される
Listクラス③getメソッドにindex(2)を渡して実行する
Listクラス③はC、2、nullなのでthis.index==indexとなる
よって『return this.value;』を実行するのでlist.get(2)はCとなる
次にiは+1されてI==3となり『System.out.println(list.get(i));』を実行
Listクラス①はA、0、List②となっているので『return this.next.get(index);』が実行される
Listクラス②のgetメソッドにindex(3)を渡して実行する
Listクラス②はB、1、List③となっているので『return this.next.get(index);』が実行される
Listクラス③getメソッドにindex(3)を渡して実行する
Listクラス③はC、2、nullなのでthis.next==nullとなる
よって『return null;』を実行するのでlist.get(3)はnullとなる
これでMainメソッドは終了する
ちなみに出力結果は
A
B
C
である
〜〜めでたしめでたし〜〜