Java道|10章のまとめ

クラスは作って終わりではない。
参照でつなぎ、引数で渡し、配列でまとめることで、オブジェクトの世界は一気に広がる。

10章では、クラスを作る基本からさらに進んで、Javaに用意されているクラスを使う方法や、オブジェクト同士をつないで扱う考え方を学びました。

ここまでくると、Javaのオブジェクト指向は「クラスを定義して、オブジェクトを1つ作る」だけではありません。
作ったオブジェクトをどう受け渡すのか。
同じオブジェクトを複数の変数でどう扱うのか。
オブジェクト同士をどう関係づけるのか。
複数のオブジェクトをどうまとめて管理するのか。

こうした、より実践的な使い方が見えてきます。

鬼滅の刃の世界でたとえると、1人の隊士だけを見ていた段階から、鬼殺隊全体の動きが見えてくる段階です。

水月という隊士を1人作る。
炎真という隊士を1人作る。
蒼真という隊士を1人作る。

ここまでは、個別の隊士を扱う段階です。

10章ではさらに進んで、

  • 隊士を指し示す札を別の場所へ渡す
  • どの隊士も指していない状態を表す
  • 隊士が師匠や仲間を参照する
  • メソッドに隊士を渡して処理する
  • 複数の隊士を名簿のように配列で管理する
  • Javaが用意している便利な道具箱を使う

という内容を学んできました。

つまり10章は、オブジェクトを単体で扱う段階から、オブジェクト同士をつなげて、まとめて、実際のプログラムらしく使う段階へ進むための章です。

クラスライブラリを使うと、Javaの道具箱を活用できる

Javaでは、自分でクラスを作るだけでなく、最初から用意されている便利なクラスを使えます。
この便利なクラスの集まりが、クラスライブラリです。

鬼滅の刃でたとえると、クラスライブラリは鬼殺隊本部が用意している巨大な道具箱です。

隊士が任務に出るたびに、刀、地図、伝令札、記録帳、計算道具をすべて一から作るのは大変です。
すでに本部に用意されている道具を使えば、任務そのものに集中できます。

Javaでも同じです。

文字列を扱いたいなら String。
文字列をあとから追加・編集したいなら StringBuffer。
文字列を整数に変換したいなら Integer。
数値計算をしたいなら Math。
入力を読み取りたいなら BufferedReader や InputStreamReader。
画面に結果を出したいなら System。

こうした標準クラスを使うことで、すべての機能を自分で作らなくても、実用的な処理を書けるようになります。

クラス主な役割鬼滅の刃でたとえると
String文字列を扱う任務の巻物を読む
StringBuffer文字列を追加・編集する追記できる作戦記録帳
Integer文字列を整数に変換する数字の札を実際の数値に変える
Math数値計算を行う鬼殺隊本部の計算道具箱
BufferedReader入力を読み込む伝令文を受け取る係
System画面へ出力する結果を掲示板へ出す係

クラスライブラリを使う良さは、次のように整理できます。

観点内容
手間を減らせるよく使う機能を一から作らなくてよい
コードが読みやすくなる何をしたい処理なのかメソッド名から分かりやすい
実用的な処理を書きやすい入力、変換、計算、表示を組み合わせられる
学習が広がる新しいクラスを調べて使う力がつく

Javaを学ぶうえでは、自分でクラスを作る力も大切です。
ただし、それと同じくらい、用意されたクラスを選んで使う力も大切です。

鬼殺隊の隊士が、自分の剣技だけでなく、本部の道具を使いこなすことで任務の幅を広げるように、Javaエンジニアもクラスライブラリを使えるようになることで、書けるプログラムの幅が大きく広がります。

クラス型の変数には、同じクラス型の変数を代入できる

10章でとても重要だったのが、クラス型変数の参照のしくみです。

クラス型の変数は、オブジェクトそのものを持っているわけではありません。
そのオブジェクトを指し示す参照を持っています。

鬼滅の刃でたとえると、変数は隊士本人ではなく、その隊士を指し示す札です。

たとえば、tanjiro という変数が1人の隊士オブジェクトを指しているとします。
そこに、zenitsu = tanjiro; のように代入すると、隊士が2人に増えるわけではありません。

zenitsu も、tanjiro と同じ隊士オブジェクトを指すようになります。

変数名指しているもの
tanjiro同じ隊士オブジェクト
zenitsu同じ隊士オブジェクト

この状態では、変数は2つあります。
でも、実体となる隊士オブジェクトは1つです。

鬼滅の刃でたとえると、1人の隊士に対して、2枚の札が向いている状態です。
札が2枚あるからといって、隊士本人が2人に増えるわけではありません。

この考え方は、Javaのオブジェクト指向でとても大切です。

参照が同じなら、状態の変化も同じ対象に見える

複数の変数が同じオブジェクトを指している場合、どちらの変数から見ても同じ実体を見ています。

そのため、片方の変数を通してオブジェクトの状態を変えると、もう一方の変数から見ても、その変化が確認できます。

鬼滅の刃でたとえると、同じ隊士の訓練記録を、2枚の札が指している状態です。
その隊士の剣技の強さや呼吸の力が変われば、どちらの札から見ても同じ更新後の記録が見えます。

状態意味
tanjiro と zenitsu が同じ隊士を指す実体は1つ
tanjiro から状態を変更する同じ隊士の状態が変わる
zenitsu から表示する変更後の状態が見える

ここで大切なのは、変数ごとに別々の隊士を持っているわけではないということです。

変数は別でも、参照先が同じなら、見ているオブジェクトは同じです。
この感覚は、フィールド、仮引数、配列を理解するときにもつながります。

null を代入すると、どのオブジェクトも指さなくなる

クラス型の変数には、null を代入できます。

null は、どのオブジェクトも指していない状態を表します。

鬼滅の刃でたとえると、隊士を追っていた札や伝令の目印が外れて、今は誰も指していない状態です。

状態意味
slayerRef が隊士を指している隊士オブジェクトを参照している
slayerRef に null を代入するどの隊士も参照していない
null の変数からメソッドを呼ぶ指す相手がいないため問題が起きる

ここで注意したいのは、null は「空のオブジェクト」ではないということです。

null は、オブジェクトが空っぽという意味ではありません。
何も指していない、という意味です。

たとえば、tanjiro がある隊士を指していて、zenitsu も同じ隊士を指しているとします。
そのあと tanjiro に null を代入すると、tanjiro はその隊士を指さなくなります。

でも、zenitsu がまだその隊士を指しているなら、その隊士オブジェクトはまだ使えます。

変数状態
tanjironull になり、どの隊士も指していない
zenitsuまだ隊士オブジェクトを指している
隊士オブジェクトzenitsu から参照できるので、まだ使える

鬼滅の刃でたとえると、1枚の札が外れても、別の札がまだ隊士を指していれば、その隊士を見失ったことにはなりません。

どの変数からも参照されなくなったオブジェクトは、Javaの管理対象になります。
不要になったオブジェクトは、Javaのガーベッジコレクションによって自動的に回収される可能性があります。

フィールドにクラス型の変数を使える

10章では、クラス型の変数をフィールドとして持てることも大切な内容でした。

オブジェクトの中には、int や double のような基本型だけでなく、別のオブジェクトへの参照をフィールドとして持たせることができます。

鬼滅の刃でたとえると、隊士オブジェクトの中に「師匠」「仲間」「相棒」「所属隊」といった別のオブジェクトへのつながりを持たせるようなものです。

たとえば、CorpsSwordsman クラスに mentor というフィールドを用意するとします。
この mentor が別の CorpsSwordsman オブジェクトを指していれば、「この隊士の師匠は誰か」という関係を表せます。

クラスフィールド意味
CorpsSwordsmanmentor師匠となる隊士を指す
CorpsSwordsmanpartner相棒となる隊士を指す
MissionTeamleader任務隊のリーダーを指す
MissionTeammember任務隊の隊士を指す

このように、フィールドにクラス型を使うと、オブジェクト同士の関係を自然に表現できます。

これは、オブジェクト指向らしさが強く出る部分です。

単に数値を保存するだけではなく、ものともののつながりを表せる。
これがクラス型フィールドの大きな意味です。

鬼滅の刃でも、隊士を1人ずつ見ているだけでは物語の広がりは見えません。
誰が誰の師匠なのか。
誰が誰と任務に出るのか。
誰が誰を支えているのか。

こうした関係を見ることで、世界が立体的になります。
Javaのオブジェクト指向も同じで、オブジェクト同士の関係を表せるようになると、プログラムの設計が一気に広がります。

メソッドの仮引数としてクラス型の変数を使える

クラス型の変数は、メソッドの仮引数としても使えます。

つまり、メソッドにオブジェクトを渡して処理できるということです。

鬼滅の刃でたとえるなら、柱が「この隊士を修行させる」「この隊士を回復させる」「この隊士を任務隊に加える」といった処理を行うイメージです。

このとき、渡しているのは隊士本人のコピーではありません。
その隊士を指す参照です。

役割内容
呼び出し元隊士オブジェクトを指す変数を持っている
実引数実際にメソッドへ渡す変数
仮引数メソッド側で受け取る変数
渡されるものオブジェクトを指す参照の値

たとえば、train(CorpsSwordsman slayer) というメソッドがあるとします。
この slayer という仮引数は、渡された隊士オブジェクトを指します。

そのため、メソッドの中で slayer.show() を呼べば、その隊士の状態を表示できます。
slayer.setSwordsman(...) のような処理をすれば、その隊士の状態を変えることもできます。

処理鬼滅の刃でたとえると
heal(CorpsSwordsman slayer)指定された隊士を回復する
train(CorpsSwordsman slayer)指定された隊士を修行させる
register(MissionTeam team)指定された任務隊を登録する
showStatus(CorpsSwordsman slayer)指定された隊士の状態を表示する

このように、クラス型の仮引数を使えると、オブジェクトを別の処理へ受け渡せるようになります。

これは、実際のJavaプログラムで非常によく使われる考え方です。

オブジェクトを配列でまとめて扱える

10章の中でも、かなり実用的なのがオブジェクト配列です。

オブジェクト配列を使うと、複数のオブジェクトを1つの配列にまとめて管理できます。

鬼滅の刃でたとえると、水月、炎真、蒼真、凛花といった複数の隊士を、鬼殺隊の隊士名簿としてまとめるようなものです。

配列の位置入っているもののイメージ
swordsmen[0]水月オブジェクトへの参照
swordsmen[1]炎真オブジェクトへの参照
swordsmen[2]蒼真オブジェクトへの参照
swordsmen[3]凛花オブジェクトへの参照

ここで大切なのは、配列要素そのものが隊士本人なのではなく、隊士オブジェクトへの参照を持っているということです。

また、オブジェクト配列では、配列を作っただけではオブジェクトはまだ作られていません。

CorpsSwordsman[] swordsmen;
swordsmen = new CorpsSwordsman[3];

これは、3人分の席を用意しただけです。

実際の隊士を作るには、各要素に new CorpsSwordsman() を代入する必要があります。

swordsmen[0] = new CorpsSwordsman();
swordsmen[1] = new CorpsSwordsman();
swordsmen[2] = new CorpsSwordsman();

この流れを整理すると、次のようになります。

手順内容鬼滅の刃でたとえると
1配列を作る隊士を並べる席を用意する
2各要素にオブジェクトを作るそれぞれの席に隊士を配置する
3配列要素からメソッドを呼ぶ各隊士に指示を出す
4for 文でまとめて処理する隊士名簿を順番に確認する

配列を使えば、for 文と組み合わせて全員に同じ処理を行いやすくなります。

たとえば、

  • 全員の状態を表示する
  • 全員に訓練値を設定する
  • 全員の名前を確認する
  • 全員を順番に任務へ登録する

といった処理が書きやすくなります。

これは、オブジェクトを1人ずつ扱う段階から、チームとしてまとめて扱う段階へ進む大切な一歩です。

10章の内容はすべて「参照」でつながっている

10章の学習内容は、一見すると別々の話に見えるかもしれません。

クラスライブラリ。
クラス型変数の代入。
null。
クラス型フィールド。
クラス型引数。
オブジェクト配列。

でも、実はこれらはすべて「参照」の考え方でつながっています。

学んだ内容参照とのつながり
クラス型変数の代入同じオブジェクトを別の変数でも指せる
nullどのオブジェクトも指していない状態を表す
クラス型フィールドオブジェクトの中に別オブジェクトへの参照を持てる
クラス型引数メソッドへオブジェクトへの参照を渡せる
オブジェクト配列配列要素がオブジェクトへの参照を持てる
クラスライブラリ用意されたクラスのオブジェクトやメソッドを使う

鬼滅の刃でたとえると、10章は「隊士本人」だけを見る章ではありません。

隊士を指す札。
隊士同士のつながり。
隊士を任務へ渡す流れ。
隊士名簿としてまとめる仕組み。
本部の道具箱を使う方法。

こうした、鬼殺隊の動き全体を見られるようになる章です。

図:10章で学んだ内容の全体像

↓クリックすると拡大表示されます。

この図が示していること

この図では、10章で学んだ内容が1つのオブジェクトを中心につながっていることを表しています。

中央の CorpsSwordsman オブジェクトは、実際に作られた隊士オブジェクトです。
右上の tanjiro と zenitsu は、同じ隊士オブジェクトを指す変数として描いています。
これにより、クラス型変数はオブジェクトそのものではなく、参照を持っていることが分かります。

左側の null カードは、変数がどの隊士も指していない状態を表しています。
右側の mentor、partner、leader は、フィールドにクラス型の変数を持たせることで、オブジェクト同士の関係を表せることを示しています。

下部左の train(CorpsSwordsman slayer) は、メソッドの仮引数にクラス型を使い、オブジェクトを受け渡せることを表しています。
下部右の swordsmen 配列は、複数の隊士オブジェクトをまとめて管理できることを示しています。

左上のクラスライブラリは、Javaが最初から用意している便利なクラスを活用できることを表しています。

ここから分かるのは、10章の内容はバラバラではなく、オブジェクトを参照し、渡し、関係づけ、まとめて扱うという流れでつながっているということです。

10章で押さえたいポイント一覧

10章で学んだ内容を、鬼滅の刃の世界観で整理すると次のようになります。

学んだ内容鬼滅の刃でのたとえ大事な理解
クラスライブラリの利用鬼殺隊本部の道具箱を使う既存の便利なクラスを活用できる
同じクラス型の代入同じ隊士を複数の札が指すオブジェクト本体のコピーではない
null の代入どの隊士も指していない札参照が切れた状態
フィールドにクラス型を使う師匠や仲間を隊士が覚えているオブジェクト同士の関係を表せる
仮引数にクラス型を使う指定された隊士を修行させるオブジェクトをメソッドへ渡せる
オブジェクト配列隊士名簿で複数人を管理する複数のオブジェクトをまとめて扱える

この表を見ると、10章の中心には「オブジェクトは単独で終わらない」という考え方があることが分かります。

オブジェクトは、変数から参照されます。
別の変数からも参照されます。
フィールドの中に参照として持たれます。
メソッドへ引数として渡されます。
配列の要素としてまとめられます。

このように、オブジェクトはプログラムの中でつながりながら使われます。

図:隊士オブジェクトを配列・引数・フィールドでつなぐ

↓クリックすると拡大表示されます。

この図が示していること

この図では、オブジェクトが配列、フィールド、仮引数によってつながる様子を表しています。

左側の swordsmen 配列は、複数の隊士オブジェクトへの参照を持っています。
swordsmen[0] は水月オブジェクト、swordsmen[1] は炎真オブジェクト、swordsmen[2] は蒼真オブジェクトを指しています。

右上の mentor や partner は、フィールドにクラス型を使うことで、別の隊士オブジェクトを指せることを表しています。
これにより、水月が炎真を師匠として持つような関係を表現できます。

右下の train(CorpsSwordsman slayer) は、メソッドの仮引数として隊士オブジェクトへの参照を受け取ることを表しています。
これにより、特定の隊士をメソッドへ渡して処理できます。

下部の null は、どの隊士も指していない状態を表します。

ここから分かるのは、配列、フィールド、仮引数は、それぞれ違う場所に見えても、すべてオブジェクトへの参照を使ってつながっているということです。

オブジェクト指向の広がりが見えてくる

10章の内容が分かると、Javaのコードの見え方がかなり変わります。

それまでは、クラスを作る、オブジェクトを作る、メソッドを呼ぶ、という単体の流れが中心でした。

10章ではそこから進んで、オブジェクトがどのように使い回されるのかが見えてきます。

見えてくること内容
オブジェクトは参照で扱われる変数はオブジェクトそのものではなく参照を持つ
同じオブジェクトを複数の変数が見られる代入によって参照先を共有できる
参照を切ることもできるnull を代入すると、どのオブジェクトも指さない
オブジェクト同士を関係づけられるフィールドにクラス型を持たせられる
オブジェクトをメソッドへ渡せる仮引数にクラス型を使える
複数のオブジェクトをまとめられるオブジェクト配列を使える
標準クラスも活用できるクラスライブラリを使える

鬼滅の刃でたとえると、1人の隊士の能力だけを見ていた段階から、鬼殺隊全体の関係性が見えてくる段階です。

誰が誰を指しているのか。
誰が誰とつながっているのか。
誰を任務へ渡すのか。
複数の隊士をどう名簿で管理するのか。
本部の道具箱をどう使うのか。

こうした視点が入ることで、オブジェクト指向の世界が一気に広がります。

実践的なJavaコードへ進むための土台

10章で学んだ内容は、どれも実際のJavaプログラムでよく使われます。

たとえば、入力された文字列を Integer で数値に変換し、Math で計算する。
複数の隊士オブジェクトを配列に入れ、for 文で順番に表示する。
メソッドへ隊士オブジェクトを渡して、状態を変更する。
フィールドに別のオブジェクトを持たせて、関係を表す。
必要がなくなった参照には null が関係することもある。

これらは、練習用の小さなコードだけでなく、実用的なプログラムでもよく出てくる考え方です。

実践での場面10章の知識
入力値を変換して計算するクラスライブラリ
同じデータを複数の場所で扱う参照の共有
使わない参照を外すnull
オブジェクト同士の関係を持たせるクラス型フィールド
オブジェクトを処理に渡すクラス型仮引数
複数データを一覧管理するオブジェクト配列

この章で学んだ内容は、次の段階へ進むための大切な橋渡しです。

配列、コレクション、継承、ポリモーフィズムなどを学ぶときにも、10章の参照の感覚が土台になります。

ここで押さえておきたい重要ポイント

10章で特に大切なポイントを整理します。

ポイント内容
クラスライブラリを使えるJavaが用意した便利なクラスを活用できる
クラス型変数は参照を持つオブジェクトそのものではなく、指す情報を持つ
同じクラス型の変数を代入できる同じオブジェクトを複数の変数で指せる
null は参照先なしを表すどのオブジェクトも指していない状態
フィールドにクラス型を使えるオブジェクトの中に別オブジェクトへの参照を持てる
仮引数にクラス型を使えるメソッドへオブジェクトを渡せる
オブジェクト配列を使える複数のオブジェクトをまとめて管理できる

鬼滅の刃の世界で考えると、10章は「隊士を1人ずつ作る段階」から、「隊士たちをつなげて動かす段階」へ進む内容でした。

隊士を指す札を使う。
同じ隊士を複数の札が指す。
札を外して、誰も指さない状態にする。
隊士が師匠や仲間を持つ。
隊士をメソッドへ渡して修行させる。
複数の隊士を名簿に並べて管理する。
そして、鬼殺隊本部の道具箱のように、Javaのクラスライブラリを活用する。

この感覚が身につくと、Javaのオブジェクト指向はかなり自然に読めるようになります。

オブジェクトは、ただ作って終わりではありません。
参照でつながり、引数で渡され、フィールドに保持され、配列でまとめられながら、プログラムの中で役割を持って動いていきます。