011-001-003

コンストラクタで自己紹介プログラム

中級

問題説明

🎯 問題の背景と目的

この問題では、Javaのオブジェクト指向プログラミングの基礎となる「コンストラクタ」を学びます。コンストラクタは、オブジェクトが作成されるときに自動的に呼ばれる特別なメソッドで、オブジェクトの初期状態を設定するために使用します。

実務では、データベースから取得したユーザー情報をオブジェクトに変換したり、設定ファイルの内容をオブジェクトとして扱う際に、コンストラクタが頻繁に使われます。この基礎を理解することで、より複雑なプログラム設計に進むことができます。

📚 前提知識の詳細説明

クラスとは何か

クラスは「設計図」のようなものです。例えば、家を建てるときの設計図が「クラス」で、実際に建てられた家が「オブジェクト」です。Personクラスという設計図から、AliceさんやBobさんという具体的な人物(オブジェクト)を作り出すことができます。

フィールドとは何か

フィールドは、オブジェクトが保持するデータです。Personクラスの場合、nameとageがフィールドです。これらはprivateというアクセス修飾子を付けて、外部から直接アクセスできないようにします(カプセル化)。

コンストラクタの役割

コンストラクタは、オブジェクトを作成するときに必要な初期化処理を行います。例えば、Personオブジェクトを作るときには必ず名前と年齢を設定する必要がある、というルールを強制できます。

📖 コードの行ごとの詳細解説

フィールドの宣言

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. `new Person("Alice", 25)`が呼ばれる
2. コンストラクタが実行される
3. パラメータnameに"Alice"が入る
4. パラメータageに25が入る
5. `this.name = name;`でフィールドnameに"Alice"が代入される
6. `this.age = age;`でフィールドageに25が代入される
7. オブジェクトの初期化が完了

### introduceメソッドの実装

```java
public String introduce() {
    return "Name: " + name + "\nAge: " + age;
}
```java

このメソッドは:
- 戻り値の型がString(文字列を返す)
- 引数なし(フィールドの値を使うだけ)
- `+`<a href="https://javadrill.tech/problems/003">演算子</a>で文字列を連結
- `\n`は改行を表すエスケープシーケンス

実行例:
- nameフィールドが"Alice"、ageフィールドが25の場合
- "Name: " + "Alice" + "\n" + "Age: " + 25
- 結果:"Name: Alice\nAge: 25"(2行の文字列)

## ⚠️ よくある間違い

### 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

## 🚀 発展的な内容

### 複数のコンストラクタ(オーバーロード)

1つのクラスに複数のコンストラクタを定義できます:

```java
public class Person {
    private String name;
    private int age;
    
    // コンストラクタ1:名前と年齢を指定
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    // コンストラクタ2:名前のみ指定(年齢はデフォルト0)
    public Person(String name) {
        this.name = name;
        this.age = 0;
    }
    
    // コンストラクタ3:引数なし(デフォルト値を設定)
    public Person() {
        this.name = "Unknown";
        this.age = 0;
    }
}
```java

### 入力検証を含むコンストラクタ

実務では、不正な値を受け取らないようにコンストラクタで検証を行います:

```java
public Person(String name, int age) {
    if (name == null || name.isEmpty()) {
        throw new IllegalArgumentException("Name cannot be empty");
    }
    if (age < 0) {
        throw new IllegalArgumentException("Age must be positive");
    }
    this.name = name;
    this.age = age;
}
```java

### ゲッターメソッドの追加

フィールドをprivateにした場合、値を取得するためのゲッターメソッドを提供するのが一般的です:

```java
public String getName() {
    return name;
}

public int getAge() {
    return age;
}
```java

## 🔗 関連する学習項目

- **カプセル化**(カテゴリ008):フィールドをprivateにして、ゲッター/セッターでアクセスする設計パターン
- **メソッドのオーバーロード**(カテゴリ012):同じ名前で異なる引数のメソッドを複数定義する技術
- **クラスの<a href="https://javadrill.tech/problems/014">継承</a>**(カテゴリ015):既存のクラスを元に新しいクラスを作る方法
- **<a href="https://javadrill.tech/problems/019/001">例外処理</a>**(カテゴリ019):不正な入力に対してエラーを投げる方法

テストケース例

※ 出力例はプログラミングの国際標準に準拠し英語で表示しています

入力:
期待される出力:
Name: Alice
Age: 25
入力:
期待される出力:
Name: Bob
Age: 30
入力:
期待される出力:
Name: Baby
Age: 0
入力:
期待される出力:
Name: Elder
Age: 100
入力:
期待される出力:
Name: Eve
Age: 18
❌ テストに失敗したケースがあります
❌ エラー発生

あなたの解答

現在のモード: 自分のコード
import java.util.Scanner;

public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// ここにコードを書いてください

sc.close();
}
}
0 B / 5 MB

残り 8 回実行可能