【Java初心者向け】クラスとインスタンスを理解する

アイキャッチ画像

Javaを学び始めて最初にぶつかる大きな壁、それが「オブジェクト指向」です。

その入り口である「クラス」と「インスタンス」。

教科書には「クラスは設計図、インスタンスは実物だ」と書いてありますが、それだけでは「ふーん、それで?」で終わってしまいがちです。

なぜプログラミングに「設計図」なんてまどろっこしい概念が必要なのか?

なぜわざわざ new しないといけないのか?

この記事を読み終える頃には、あなたの頭の中にある「クラス」のイメージが、ぼんやりした鏡からクリアな写真に変わっているはずです。

目次

そもそも「クラス」が必要な理由を考えよう

まず、クラスを使わずに「車」を表現しようとするとどうなるか、想像してみてください。

例えば、2台の車(スポーツカーとファミリーカー)のデータを管理するプログラムを書くとします。

// 1台目のデータ
String car1Model = "フェラーリ";
String car1engineType = "ガソリン";
String car1Color = "赤";
int car1Speed = 0;

// 2台目のデータ
String car2Model = "プリウス";
String car2engineType = "ハイブリッド";
String car2Color = "白";
int car2Speed = 0;

// 加速させる処理(1台目)
car1Speed += 10;
System.out.println(car1Model + "が加速しました");

これ、車が100台になったらどうなるでしょうか?変数の管理だけでパニックになりますよね。「加速する」という処理も、100箇所に書くわけにはいきません。

そこで登場するのが「クラス」です。

クラスは、バラバラになりがちな「データ(属性)」と「処理(振る舞い)」を一つのパッケージにまとめるための枠組みなのです。

【設計図】Carクラスの構造を解剖する

まず結論から。

クラスとは「モノを作るための設計図」です。

設計図とは、

「こういうデータを持ち」
「こういう振る舞いをする」

というルールの集合体です。

たとえば、自動車の設計図を考えてみます。

ここでいう設計図とは、

・どんな項目を持つのか
・どんな機能を備えるのか

を定義したルールブックです。

例えば、新しいスポーツカーを設計するとします。

設計図に書かれる内容はこうです。

・車種(model)
・色(color)
・エンジンタイプ(engineType)
・現在の速度(speed)

そして機能として

・加速する
・停止する

を持つとします。

改めて、今回使用する Car クラスを見てみましょう。

public class Car {
    // フィールド(属性・データ)
    String model;       // 車種
    String color;       // 色
    String engineType;  // エンジンタイプ
    int speed;          // 現在の速度

    // メソッド(振る舞い・操作)
    void accelerate() {
        System.out.println("加速します");
        speed += 10; // 速度を上げる処理を追加
    }

    void brake() {
        System.out.println("停止します");
        speed = 0;
    }
}

フィールド:車が「持っている」もの

modelcolor は、その車を特徴づけるデータです。

これらを「フィールド」や「メンバ変数」と呼びます。

設計図に「ここに名前を書く欄がありますよ」「ここに色を塗る場所がありますよ」という空の項目を作っている状態です。

メソッド:車が「できる」こと

accelerate()brake() は、その車ができる操作です。

これを「メソッド」と呼びます。

設計図に「アクセルを踏んだらこう動く」「ブレーキを踏んだらこう止まる」という動作マニュアルを書き込んでいる状態です。

重要: この時点では、まだ「車」は存在しません。あくまで「車を作るなら、こういう項目と機能を持たせよう」という定義だけが存在している状態です。インスタンス化で実態(命)を作成します。

設計図ができたら、次は本物の車を作ります。Javaでは new 演算子を使って、設計図から実体を作り出します。
これを「インスタンス化(生成)」と言います。

public class Main {
    public static void main(String[] args) {
        // 1. インスタンスの生成(車を一台作る)
        Car myCar = new Car();

        // 2. フィールドに値を代入(色を塗ったり車種を決めたりする)
        myCar.model = "フェラーリ";
        myCar.engineType = "ガソリン";
        myCar.color = "赤";
        myCar.speed = 0;

        // 3. メソッドを呼び出す(操作する)
        myCar.accelerate();
    }
}
paiza.io で確認する方法
//public class Car {
class Car {
    // フィールド(属性・データ)
    String model;       // 車種
    String color;       // 色
    String engineType;  // エンジンタイプ
    int speed;          // 現在の速度

    // メソッド(振る舞い・操作)
    void accelerate() {
        System.out.println("加速します");
        speed += 10; // 速度を上げる処理を追加
    }

    void brake() {
        System.out.println("停止します");
        speed = 0;
    }
}
public class Main {
    public static void main(String[] args) {
        // 1. インスタンスの生成(車を一台作る)
        Car myCar = new Car();

        // 2. フィールドに値を代入(色を塗ったり車種を決めたりする)
        myCar.model = "フェラーリ";
        myCar.engineType = "ガソリン";
        myCar.color = "赤";
        myCar.speed = 0;

        // 3. メソッドを呼び出す(操作する)
        myCar.accelerate();
    }
}

new が裏側でやっていること

new Car() が実行された瞬間、起きていることは大きく3つです。

①メモリ上に Car 型のオブジェクトを置くための領域が確保される
ここに makermodel のようなフィールドが入る箱が用意されます。

②その確保されたオブジェクトに対して コンストラクタが実行される
初期値が設定されるのはこのタイミングです。

③そのオブジェクトの場所を示す「参照値」が返される。
それを受け取るのが myCar です。

「個体差」こそがインスタンスの真骨頂

「わざわざ設計図と実体を分けなくても、最初から実体を作ればいいじゃないか」と思うかもしれません。

しかし、オブジェクト指向の真価は「同じ設計図から、異なるデータを持つ複数の実体を作れること」にあります。

// スポーツカーを生成
Car sportsCar = new Car();
sportsCar.model = "フェラーリ";
sportsCar.engineType = "ガソリン";
sportsCar.color = "赤";
sportsCar.speed = 0;

// ファミリーカーを生成
Car familyCar = new Car();
familyCar.model = "プリウス";
familyCar.engineType = "ハイブリッド";
familyCar.color = "白";
familyCar.speed = 0;

ここで非常に重要なのが、「メモリ上の場所が違う」ということです。

もし sportsCar.accelerate() を呼び出してスピードを上げても、familyCar のスピードはピクリとも動きません。
なぜなら、彼らは同じ Car クラスというルールに従っていますが、メモリ上では全く別々の存在だからです。

  • クラス: 共通のルール(「車は色と速度を持つ」)
  • インスタンス: 個別の現実(「私の車は赤で100km」「あなたの車は白で0km」)

この「型(クラス)」と「実体(インスタンス)」の分離によって、私たちは複雑なシステムを整然と管理できるようになります。

よくある疑問:なぜ「フィールド」に直接値を入れないの?

初心者の方からよく出る質問に、「クラスの中に String color = "赤"; と直接書いちゃダメなの?」というものがあります。

// これをやっちゃうと...
public class Car {
    String color = "赤"; // 全ての車が最初から赤になる
}

これをやってしまうと、この設計図から作られる車はすべて出荷時から赤色になってしまいます。
もちろん「デフォルトの色」として設定するのはアリですが、クラスの本質は「汎用的な枠組み」であることです。

「色はインスタンスごとに決めるもの」という柔軟性を持たせるために、クラス側では型だけを定義しておくのが基本です。

まとめ:クラスとインスタンスの「本質」

最後に、今回学んだことを整理しましょう。

概念役割例えJavaでの表現
クラス定義・枠組み設計図、金型、レシピpublic class Car { ... }
インスタンス実体・データ実車、大判焼き、料理new Car();

なぜこの仕組みが必要なのか?

再利用性
一度 Car クラスを作れば、何百台でも車を量産できる。

独立性
各インスタンスが自分のデータを持つため、お互いに干渉せず安全に処理できる。

保守性
「車の加速方法を変えたい」と思ったら、Car クラスの accelerate メソッドを一箇所直すだけで、すべての車に適用される。

Javaを学ぶことは、この「設計図(クラス)」をいかに美しく、機能的に描くかを学ぶことと言っても過言ではありません。

次のステップへのヒント

クラスとインスタンスの関係がわかったら、次は「コンストラクタ」を学んでみましょう。

今は new Car() をした後に一行ずつ model = "..." と値を代入していますが、コンストラクタを使えば、「車を誕生させると同時に、名前と色を決定する」というより自然な書き方ができるようになります。

「設計図から車が組み上がる瞬間に、色を塗ってしまう」イメージです。
これができると、さらにJavaらしいコードが書けるようになりますよ!

よかったらシェアしてね!
  • URLをコピーしました!
目次