011-001-003
コンストラクタで自己紹介プログラム
中級
問題説明
📥 入力形式
標準入力から2行を読み込みます:
- 1行目:名前(文字列、スペースなし)
- 2行目:年齢(0以上の整数)
📤 出力形式
Name: [名前]
Age: [年齢]
🎯 問題の背景と目的
この問題では、Javaのオブジェクト指向プログラミングの基礎となる「コンストラクタ」を学びます。コンストラクタは、オブジェクトが作成されるときに自動的に呼ばれる特別なメソッドで、オブジェクトの初期状態を設定するために使用します。
実務では、データベースから取得したユーザー情報をオブジェクトに変換したり、設定ファイルの内容をオブジェクトとして扱う際に、コンストラクタが頻繁に使われます。この基礎を理解することで、より複雑なプログラム設計に進むことができます。
📚 前提知識の詳細説明
クラスとは何か
クラスは「設計図」のようなものです。例えば、家を建てるときの設計図が「クラス」で、実際に建てられた家が「オブジェクト」です。Personクラスという設計図から、AliceさんやBobさんという具体的な人物(オブジェクト)を作り出すことができます。
フィールドとは何か
フィールドは、オブジェクトが保持するデータです。Personクラスの場合、nameとageがフィールドです。これらはprivateというアクセス修飾子を付けて、外部から直接アクセスできないようにします(カプセル化)。
コンストラクタの役割
コンストラクタは、オブジェクトを作成するときに必要な初期化処理を行います。例えば、Personオブジェクトを作るときには必ず名前と年齢を設定する必要がある、というルールを強制できます。
📖 コードの行ごとの詳細解説
Scannerを使った入力読み込み
Scanner sc = new Scanner(System.in);
String name = sc.next(); // 名前を読み込む
int age = sc.nextInt(); // 年齢を読み込む
```java
Scannerを使って標準入力から名前と年齢を読み込み、その値をPersonオブジェクトの生成に使います。
### フィールドの宣言
```java
private String name;
private int age;
```java
この2行で、Personクラスが持つデータ(フィールド)を定義しています。
- `private`:このフィールドは外部から直接アクセスできません。クラス内部でのみ使用できます。
- `String name`:文字列型の変数nameを宣言。人の名前を保存します。
- `int age`:整数型の変数ageを宣言。人の年齢を保存します。
この時点では、これらの<a href="https://javadrill.tech/problems/001">変数</a>は宣言されただけで、値は入っていません(nullまたは0)。
### コンストラクタの定義
```java
public Person(String name, int age) {
```java
コンストラクタの特徴:
- クラス名(Person)と全く同じ名前
- 戻り値の型を書かない(voidも書かない)
- `public`にすることで、外部から`new Person(...)`として呼び出せる
- 引数として、初期化に必要なデータ(名前と年齢)を受け取る
### thisキーワードの使用
```java
this.name = name;
this.age = age;
```java
`this`は「このオブジェクト自身」を指すキーワードです。
- `this.name`:このオブジェクトのnameフィールド
- `name`:コンストラクタの引数として渡されたname
なぜ`this`が必要なのか:
フィールド名とパラメータ名が同じ場合、`this`を付けないとどちらを指しているのか区別できません。`this.name = name;`と書くことで、「左側はフィールド、右側はパラメータ」と明確に区別できます。
実行の流れ:
1. Scannerで読み込んだ名前と年齢を使って`new Person(name, age)`が呼ばれる
2. コンストラクタが実行される
3. パラメータnameに入力値が入る
4. パラメータageに入力値が入る
5. `this.name = name;`でフィールドnameに代入される
6. `this.age = age;`でフィールドageに代入される
7. オブジェクトの初期化が完了
### introduceメソッドの実装
```java
public String introduce() {
return "Name: " + name + "\nAge: " + age;
}
```java
このメソッドは:
- 戻り値の型がString(文字列を返す)
- 引数なし(フィールドの値を使うだけ)
- `+`<a href="https://javadrill.tech/problems/003">演算子</a>で文字列を連結
- `\n`は改行を表すエスケープシーケンス
## ⚠️ よくある間違い
### 1. コンストラクタに戻り値の型を書いてしまう
間違った例:
```java
public void Person(String name, int age) { // ❌ voidは不要
this.name = name;
this.age = age;
}
```java
理由:コンストラクタは戻り値の型を書きません。voidを書くと、これは普通のメソッドになってしまい、コンストラクタとして機能しません。
正しい書き方:
```java
public Person(String name, int age) { // ✅ 戻り値の型なし
this.name = name;
this.age = age;
}
```java
### 2. thisを使わずにフィールドに代入
間違った例:
```java
public Person(String name, int age) {
name = name; // ❌ 何も起こらない
age = age; // ❌ 何も起こらない
}
```java
理由:`name = name;`と書くと、パラメータnameにパラメータnameを代入しているだけで、フィールドには何も代入されません。フィールドの値は変わらず、nullまたは0のままです。
正しい書き方:
```java
public Person(String name, int age) {
this.name = name; // ✅ フィールドに代入
this.age = age; // ✅ フィールドに代入
}
```java
### 3. フィールドを宣言し忘れる
間違った例:
```java
public class Person {
// ❌ フィールドがない
public Person(String name, int age) {
this.name = name; // エラー:nameフィールドが存在しない
this.age = age; // エラー:ageフィールドが存在しない
}
}
```java
正しい書き方:
```java
public class Person {
private String name; // ✅ フィールド宣言
private int age; // ✅ フィールド宣言
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
```java
## 🔗 関連する学習項目
- **カプセル化**(カテゴリ008):フィールドをprivateにして、ゲッター/セッターでアクセスする設計パターン
- **メソッドのオーバーロード**(カテゴリ012):同じ名前で異なる引数のメソッドを複数定義する技術
- **クラスの<a href="https://javadrill.tech/problems/014">継承</a>**(カテゴリ015):既存のクラスを元に新しいクラスを作る方法
- **<a href="https://javadrill.tech/problems/019/001">例外処理</a>**(カテゴリ019):不正な入力に対してエラーを投げる方法
