前回の記事では、「クラス=設計図」「インスタンス=実物」「newで実物を作る」という基本をお伝えしました。
しかし、ここで一つ重要な問いがあります。 「newを実行した瞬間、Javaの内部ではただメモリを確保しているだけでしょうか?」
実は違います。new の裏側では、ある特別なメソッドが必ず実行されています。
それが、今回解説する「コンストラクタ」です。
コンストラクタとは何か?
コンストラクタを一言でいうと、 「インスタンスが作られた瞬間に、最初に実行される特別な処理」のことです。
設計図から実物が生まれるその瞬間、「初期状態をどうするか」を決める役割を持っています。
車を例に考えてみましょう。
もし、
- 車種未設定
- 速度不明(何キロ出ているか分からない)
こんな状態で車が誕生して、そのまま公道を走り出したらどうでしょう?
それはもはや車ではなく、ただの危険物ですよね。
プログラミングでも同じです。
「作る瞬間に必要な情報を必ずセットする」。
これを強制する仕組みがコンストラクタなのです。
まずは「コンストラクタなし」の危うさを知る
以前の Car クラスはこのような形でした。
この設計図を使って、インスタンスをこう作っていましたね。
// スポーツカーを生成
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;さて、ここで問題です。 もし、作成した後に model や engineType を設定し忘れたらどうなるでしょうか?
Javaの世界では、中身が空っぽの「不完全な車」が誕生してしまいます。これは設計として非常に危険です。「使う人がちゃんと値を入れ忘れないだろう」という使い手の善意に依存している状態だからです。
コンストラクタで「製造ルール」を定義する
では、安全に車を作る仕組み(コンストラクタ)を取り入れてみましょう。
public class Car {
// フィールド(属性・データ)
String model; // 車種
String color; // 色
String engineType; // エンジンタイプ
int speed; // 現在の速度
// これがコンストラクタ!
public Car(String model, String color, String engineType) {
this.model = model;
this.color = color;
this.engineType = engineType;
this.speed = 0; // 誕生時は必ず0km/h
}
// メソッド(振る舞い・操作)
void accelerate() {
System.out.println("加速します");
speed += 10; // 速度を上げる処理を追加
}
void brake() {
System.out.println("停止します");
speed = 0;
}
}ここで覚えるべきポイントは3つです。
- クラス名と全く同じ名前で書く
- 戻り値を書かない(
voidすら書かない) newした瞬間に自動で呼ばれる
これを使うと、インスタンスの作り方はこう変わります。
Car sportsCar = new Car("フェラーリ", "赤", "ガソリン");この一行だけで、「車種はフェラーリ、エンジンタイプはガソリン、色は赤、速度は0」という状態が確定します。これで、設定漏れのある未完成な車は二度と生まれません。
初心者の壁「this」の正体
コンストラクタを書くと、必ず目にするのが this.model= model; という記述です。 「同じ名前が2つある!どっちがどっち?」と混乱しがちですが、実はシンプルです。
- 左側の
this.model: このクラスの「フィールド(変数)」 - 右側の
model: 外から渡された「引数(データ)」
this は、「このインスタンス自身」を指すキーワードです。 「外から届いた『フェラーリ』という値を、私(このインスタンス)の model 欄に書き込んでね!」という意味になります。
「書いていない」のに動く理由:デフォルトコンストラクタ
実は、コンストラクタを自分で書かなくても今までのプログラムは動いていました。
なぜでしょうか?
それは、Javaが気を利かせて「中身が空っぽのコンストラクタ」を自動で作ってくれていたからです。
これをデフォルトコンストラクタと呼びます。
public class Car {
// フィールド(属性・データ)
String model; // 車種
String color; // 色
String engineType; // エンジンタイプ
int speed; // 現在の速度
// デフォルトコンストラクタ!
public Car() {
// 中身は空っぽ
}
// メソッド(振る舞い・操作)
void accelerate() {
System.out.println("加速します");
speed += 10; // 速度を上げる処理を追加
}
void brake() {
System.out.println("停止します");
speed = 0;
}
}しかし、ここに一つ罠があります。 自分で一つでもコンストラクタを書くと、この自動生成は行われません。
つまり、引数ありのコンストラクタを作った後に new Car(); と書くとエラーになります。Javaはこう言っているのです。 「製造ルールを自分で決めたんだから、今後はそのルール(引数)をちゃんと守って作ってね!」 非常に合理的だと思いませんか?
コンストラクタの本質:正しい状態でしか作らせない
「コンストラクタは初期値をセットするためのものでしょ?」
半分正解ですが、本質はもっと深いところにあります。
本質とは、「正しい状態でしかインスタンスを作らせない(不正な存在を許さない)」ことです。
例えば、コンストラクタの中にチェック処理を入れることもできます。
public Car(String model, String color, String engineType) {
if (model == null) {
throw new IllegalArgumentException("モデルは必須です!");
}
this.maker = maker;
this.model = model;
}これで、メーカー名が不明な車が生まれるのを物理的に阻止できます。
クラスは単なるデータの箱ではありません。状態を厳格に管理する装置なのです。
まとめ:設計図から「製造ルール」へ
- コンストラクタは生成時に自動実行される。
- クラス名と同じ名前で、戻り値はなし。
- 「正しい状態」でインスタンスを誕生させるための防衛策。
設計図(クラス)を理解し、製造ルール(コンストラクタ)を理解しました。 すると、次の疑問が湧いてきませんか? 「せっかくコンストラクタで正しく作ったのに、後から speed = -100 とか書き換えられたら台無しじゃない?」
鋭いですね。その「勝手に触らせない」ための仕組みが、次回のテーマ「カプセル化」です。 一歩ずつ、オブジェクト指向の深みへ進んでいきましょう!
いかがでしょうか。 非常に論理的で分かりやすい構成でしたので、読者も「なぜコンストラクタが必要か」がスッと理解できるはずです。
次は、この記事の最後に触れた「カプセル化(privateとgetter/setter)」についての解説記事を作成しましょうか?

