インスタンスを作る

生田 陸人
LuaGate エンジニア / 現役エンジニア
編集 LuaGate編集部

インスタンスを作る とは

クラスから実体 (インスタンス) を作る方法と new 演算子の使い方を学ぼう。本レッスンでは、インスタンスを作る の基本から実際の使いどころまでを整理し、現場で迷わず使える形に落とし込みます。

インスタンスを作る

前のレッスンまでで、Java ではすべてのコードが class の中に入ること、そして public static を付けたメソッドはクラス名から直接呼び出せることを学びました。今回からはいよいよ、クラスから インスタンス (instance) を作って使う、オブジェクト指向の入り口に踏み込みます。

インスタンスとは何か

クラスは「設計図」、インスタンスは「設計図から作られた実体」です。たとえば「Book というクラス」は本そのものではなく、「本というものはどんな属性 (タイトル / 著者) と振る舞い (読む / しおりを挟む) を持つか」を書いた設計図に過ぎません。実際に本棚に並ぶ 1 冊 1 冊が インスタンス です。

身近なたとえで言うと、たい焼きの型たい焼き本体 の関係に近いです。型 (クラス) は 1 つしかありませんが、その型を使えば、あんこ入り、クリーム入り、白いたい焼き、と何個でも別々のたい焼き (インスタンス) を焼くことができます。

「クラス = 設計図、インスタンス = 実体」というフレーズはこの先 100 回くらい登場します。最初のうちはピンとこなくて当然なので、まずは「new を 1 回押すたびに 1 個実体が生まれる」とだけ覚えておけば十分です。

クラスとインスタンスの関係を図にすると次のとおりです。1 つの Book クラスから、別々のインスタンスがいくつも生まれているのが分かります。

diagram (will load when visible)

new 演算子で実体を作る

インスタンスを作るには、new という専用の演算子を使います。書き方はとてもシンプルです。

Java

new Book();

たったこれだけで、Book クラスを基にした新しいインスタンスが 1 つメモリ上に生まれます。Book() の部分はコンストラクタの呼び出しで、引数を取ることもできますが、今回はまず 引数なし の最もシンプルな形を扱います。

ただし、これだけでは作ったインスタンスをすぐ捨ててしまうのと同じです。せっかく作った実体に名前を付けてあげないと、後から触ることができません。そこで登場するのが 変数への代入 です。

変数に代入してアクセスする

作ったインスタンスは、必ず変数に入れて使います。書き方は次のとおりです。

Java

Book b = new Book(); String message = b.read();

左から右に向かって、3 つのパートに分かれているのが見えますか。型 Book、変数名 b、そして = new Book(); で実体を作って代入しています。これで b という名前を通して、いつでも先ほどの Book インスタンスにアクセスできるようになりました。

  • Book bBook 型の変数 b を宣言する (まだ中身は空)
  • new Book() — 新しい Book インスタンスを 1 つ作る
  • = で両者を結ぶ — 変数 b がそのインスタンスを指すようになる

「型を 2 回書いてるみたい」と感じるかもしれません。左の Book は「この変数にはこれから Book を入れますよ」という宣言、右の Book() は「実際に Book を作りますよ」という命令で、役割が違います。書き慣れると体が勝手に覚えます。

インスタンスに紐づくメソッドを呼び出すときは、変数名の後ろにドットを付けて b.read() のように書きます。これは「b が指している Book インスタンスの read を呼んでください」という意味です。static メソッドのときに使った Solution.helloWorld() のクラス名・ドット・メソッド名のリズムと、見た目はとても似ていますが、左側にあるのが クラス名変数名 かで意味が大きく変わります。

1 つのクラスから複数のインスタンスを作る

クラスは設計図なので、同じクラスから複数のインスタンスを作ることができます。たとえば次のように書くと、別々の Book が 3 つ生まれます。

Java

Book b1 = new Book(); Book b2 = new Book(); Book b3 = new Book();

b1 b2 b3 はそれぞれ別の実体です。b1 の中身を書き換えても、b2 b3 には影響しません。「同じクラスから生まれた別のインスタンス」というのは、双子の兄弟のような関係に近いかもしれません。同じ設計図から生まれているけれど、それぞれが独立した存在です。

インスタンスはメモリ上に作られます。new するたびに新しい場所にデータが確保され、変数はその場所を指し示す 参照 を持ちます。最初は深く考えなくて大丈夫ですが、「new の回数 = メモリ上に生まれる実体の数」とだけ覚えておきましょう。

Solution の中に Book クラスを書く

chotdekiru の Java Playground では 1 つの Solution.java の中にコードを書きます。別ファイルを作る代わりに、Solution クラスの中に Book をネストして書くのが一番手軽です。書き方は次の 2 通りがあります。

まずは static を付けて書く static inner class パターンです。これは外側のクラスのインスタンスがなくても使えるので、coding 問題ではこれが鉄板です。

Java

public class Solution { static class Book { String read() { return "Hello, Object!"; } } public static String instantiateAndGet() { Book b = new Book(); return b.read(); } }

もう 1 つの書き方は、static を付けない通常の inner class です。こちらは外側のインスタンスとセットで使う前提なので、static メソッドからは少し扱いづらく、最初のうちは避けて構いません。

Java

public class Solution { class Book { String read() { return "Hello, Object!"; } } }

細かい話ですが、Java 公式の教科書ではトップレベルの別ファイルでクラスを書くのが王道です。static inner class は、chotdekiru のように 1 ファイルで完結させたいときに便利な書き方として覚えておくとよいです。

よくある間違い

インスタンス化まわりで最初によくつまずく落とし穴を 3 つ紹介します。

  • new を書き忘れるBook b = Book(); のように new を抜いてしまうと、「Book という名前のメソッドを呼ぼうとした」と解釈されてコンパイルエラーになります。インスタンスを作るときは必ず new を先頭に付けてください
  • 変数宣言と new を混同するBook b; だけで終わってしまうと、変数 b は宣言されていますが中身は null のままです。この状態で b.read() を呼ぶと実行時に NullPointerException が飛んできます。必ず = new Book(); まで書ききりましょう
  • static メソッドをインスタンスから呼ぼうとするSolution.helloWorld() のような static メソッドは、本来クラス名から呼ぶものです。インスタンスを作って s.helloWorld() と書いてもエラーにはなりませんが、警告が出るうえに意味も薄れます。static はクラス、それ以外はインスタンス、と使い分けましょう

もう 1 つ、初心者を混乱させがちなのが「クラス名と変数名がそっくり」問題です。Book book = new Book(); のように、型 Book と変数名 book は別物ですが、書く側はつい同じものに見えてしまいます。Java では「型 → 変数名 → 値」の順に並ぶ、というリズムを意識すると整理しやすくなります。

エラーメッセージの中でも NullPointerException は Java エンジニアが一生付き合うことになる相棒です。出てきたら「どの変数が null のまま使われたのか」を真っ先に疑うクセを今のうちから付けておきましょう。

やってみよう

それでは課題に挑戦しましょう。手順は次のとおりです。

  1. 右側のエディタを開く
  2. Solution クラスの中に static class Book を書き、その中に String read() メソッドを定義する
  3. instantiateAndGet メソッドの中で Book b = new Book(); のようにインスタンスを作る
  4. return b.read(); のように呼び出した結果を返す
  5. 「実行」ボタンを押してテストが緑になることを確認する

慣れてきたら、Book インスタンスを 2 個 3 個と増やしてみたり、Book クラスにフィールド (String title) を追加してみたり、自由に遊んでみてください。次のレッスンからはこのインスタンスにフィールドとコンストラクタを持たせて、よりリアルな「設計図と実体」の関係に踏み込んでいきます。

クラスとインスタンスは Java の中心テーマです。ここでつまずいても焦らず、new を押すたびに新しい実体が生まれているイメージを大事にしながら、何度も手を動かして体に馴染ませていきましょう。

よくある質問

Q. クラスとインスタンスの違いは?

A. クラスは設計図、インスタンスは設計図から作った具体的なオブジェクトです。Person クラスから new Person('Alice', 20) でインスタンスを作ると、それぞれが別の name と age を持ちます。クラスは 1 つでもインスタンスは何個でも作れます。

Q. インスタンスを作る new は何をしていますか?

A. メモリを確保し、コンストラクタを呼び出し、初期化されたオブジェクトの参照を返します。Java/JavaScript は new 必須、Python は new なしで Person() と呼ぶだけ(内部的に new + init が走る)です。

Q. 1 つのクラスから複数のインスタンスを管理するには?

A. ArrayList / 配列 / Map に格納するのが定石です。各インスタンスは独立した状態を持つので、ループで for (Product p : products) のように回せます。集合操作(合計、最大値)は Stream API(Java)/ map・reduce(JS)が便利です。

次のレッスン

次は コンストラクタ で、クラスから実体 (インスタンス) を作る方法と new 演算子の使い方を学ぼう を学びます。

事前確認 — 進む前に次の 3 つができることを確認しましょう。

  1. インスタンス化 の要点を自分の言葉で説明できる
  2. このレッスンの最小コード (または操作手順) を見ずに書ける
  3. 練習問題やクイズで間違えた箇所を読み直して理解した

理解度チェック (30 秒)

Q. インスタンス化 とは何か、1 文で説明してください。

この章のポイント

A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。

関連レッスン

要件

  1. Solution クラスの中に Book クラスをネストで定義すること (static class Book 推奨)
  2. Book クラスに read() のような戻り値が String のメソッドを持たせ、"Hello, Object!" を返すこと
  3. instantiateAndGet() の中で new Book() でインスタンスを作り、その戻り値を return で返すこと

入出力例

test-cases.txt

instantiateAndGet()"Hello, Object!"

ヒント

main.java
main.java
学習モード

メモ

インスタンスを作る

⌘S で保存