JAVA練習問題4-3:クラスメンバを理解しよう

記事内に商品プロモーションを含む場合があります

JAVAの初心者向け問題4-3:クラスメンバを理解しよう

この問題を解くために必要な知識:
【レベル1~3の知識】
コメントの書き方、変数と定数、基本データ型とプリミティブ型、四則演算と論理演算、入力と出力(Scannerクラス)、配列、分岐処理(if、if~else、switch)、繰り返し処理(for、while、do~while)、メソッドの定義と呼び出し、メソッドの戻り値、メソッドのオーバーロード、例外処理(try-catch文、throws、throw)、クラスの定義と使用、インスタンス、コンストラクタ、コレクションの基礎、コレクション(List, ArrayList)、コレクション(HashSet, TreeSet)、コレクション(HashMap, TreeMap)

【レベル4の知識】
インスタンスメソッド、ゲッターとセッター、カプセル化、クラスメンバ、クラスの継承抽象クラスインターフェース

<<前の問題 問題集Top 次の問題>>

JAVAの文法「クラスメンバ」とは

ここではクラスメンバの意味や使い方を復習します。必要ない方はここをクリックして練習問題へ飛びましょう。



Javaを学び始めると、すぐに「クラス」と「オブジェクト」という用語に出会います。

このクラスには「クラスメンバ」という重要な概念があります。今回は、クラスメンバについてわかりやすく解説していきます。

クラスメンバとは?

クラスメンバとは、クラス内に定義される要素のことです。具体的には、以下の2つのタイプがあります。

  • フィールド(変数):クラスが保持するデータ(状態)を表します。
  • メソッド:クラスが提供する機能(動作)を定義します。

クラスは「設計図」と呼ばれますが、この設計図の中に組み込まれているパーツがフィールドやメソッドです。これらをクラスメンバと呼びます。

フィールド(変数)

クラス内で定義される変数をフィールドと呼びます。フィールドは、そのクラスのオブジェクトが持つ「状態」を表現します。

たとえば、「人」を表すクラスを考えた場合、フィールドは「名前」や「年齢」といった人に関する情報を保持します。

public class Person {
    // フィールド
    String name;
    int age;
}

このように、nameageという2つのフィールドが定義されています。

これらは、Personクラスの各オブジェクト(個々の人)が持つデータとなります。

メソッド

次に、クラスが持つ動作や機能を定義するのがメソッドです。メソッドは、オブジェクトに対して「何をさせるか」を決めます。

例えば、Personクラスに「自己紹介をする」という機能を持たせたい場合、次のようにメソッドを定義します。

public class Person {
    // フィールド
    String name;
    int age;
    
    // メソッド
    void introduce() {
        System.out.println("私の名前は" + name + "です。年齢は" + age + "歳です。");
    }
}

ここで定義されたintroduce()メソッドは、Personオブジェクトが持つnameageを使って、自己紹介を行う機能です。

クラスメンバの種類

クラスメンバにはさらに、インスタンスメンバとクラスメンバ(staticメンバ)の2種類があります。これらは、使い方や役割が少し異なります。

インスタンスメンバ

通常のフィールドやメソッドは、インスタンスメンバと呼ばれます。これらはオブジェクトごとに異なる値や動作を持ちます。

例として、異なる名前や年齢を持つ2人のPersonオブジェクトを考えます。

Person person1 = new Person();
person1.name = "太郎";
person1.age = 25;

Person person2 = new Person();
person2.name = "花子";
person2.age = 30;

person1person2はそれぞれ異なるnameageの値を持っています。これは、インスタンスごとに異なる状態を持つインスタンスメンバの特徴です。

クラスメンバ(staticメンバ)

一方、staticキーワードを使って定義されたメンバは、クラス全体で共有されるメンバです。

これをクラスメンバと呼びます。クラスメンバは、すべてのインスタンスで同じ値を共有します。

public class Person {
    // クラスメンバ
    static int population = 0;
    
    String name;
    int age;

    // コンストラクタ
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
        population++; // 人が増えるたびに人口を増やす
    }
}

この例では、populationという変数はstaticキーワードで定義されています。

populationは、Personクラスの全てのオブジェクトで共有される値であり、Personオブジェクトが作られるたびに増えていきます。

Person person1 = new Person("太郎", 25);
Person person2 = new Person("花子", 30);

System.out.println(Person.population); // 2

staticメンバは、インスタンスごとに異なる値を持たないため、クラス自体に結びついています。

そのため、Person.populationのように、クラス名でアクセスします。

まとめ

クラスメンバは、クラスに定義されるフィールドメソッドを指します。

そして、クラスメンバにはインスタンスメンバとクラスメンバ(staticメンバ)の2種類があります。

  • インスタンスメンバはオブジェクトごとに異なる値を持ちます。
  • クラスメンバ(staticメンバ)はクラス全体で共有され、すべてのインスタンスで同じ値を持ちます。

Javaのクラスを設計する際は、これらのメンバの役割を理解し、適切に使い分けることで、効率的でわかりやすいコードを書くことができます。

初心者にとっては少し難しく感じるかもしれませんが、実際にコードを書きながら試してみることで、理解が深まっていくでしょう。




JAVA練習問題4-3:クラスメンバを使って銀行口座管理プログラムを作ろう

次の条件に従って「クラスメンバ」を利用する銀行口座管理プログラムを作成しましょう。

この問題の要件

以下の要件に従いプログラムを作成して下さい。

  1. BankAccountクラスを作成し、以下のメンバ変数を持たせること。
    • accountHolder(口座名義): インスタンス変数
    • balance(残高): インスタンス変数
    • totalAccounts(総口座数): クラスメンバ
  2. BankAccountクラスに以下のメソッドを追加すること。
    • コンストラクタ: accountHolderbalanceを初期化し、totalAccountsを1増加させる。
    • depositメソッド: 入金額を受け取り、残高に加算する。
    • withdrawメソッド: 引き出し額を受け取り、残高から減算する。
    • displayAccountInfoメソッド: 口座名義と残高を表示する。
    • displayTotalAccountsメソッド: 総口座数を表示する(静的メソッド)。
  3. メインメソッドで以下を行うこと。
    • 3つの銀行口座オブジェクトを作成する。
    • 各口座に入金および引き出し操作を行う。
    • 各口座の情報を表示する。
    • 総口座数を表示する。

ただし、以下のような実行結果となること。

----- ↓出力される結果の例↓ -----

口座1の名義を入力してください:
山田太郎
口座1の初期残高を入力してください:
1000.0
口座2の名義を入力してください:
鈴木花子
口座2の初期残高を入力してください:
1500.0
口座3の名義を入力してください:
佐藤一郎
口座3の初期残高を入力してください:
2000.0
山田太郎さんの口座に入金する金額を入力してください:
500.0
山田太郎さんの口座から引き出す金額を入力してください:
300.0
鈴木花子さんの口座に入金する金額を入力してください:
600.0
鈴木花子さんの口座から引き出す金額を入力してください:
200.0
佐藤一郎さんの口座に入金する金額を入力してください:
700.0
佐藤一郎さんの口座から引き出す金額を入力してください:
400.0
口座名義: 山田太郎, 残高: 1200.0
口座名義: 鈴木花子, 残高: 1900.0
口座名義: 佐藤一郎, 残高: 2300.0
総口座数: 3

----- ↑出力される結果の例↑ -----

この問題を解くヒント

1からコードを組み立てることが難しい場合は、以下のヒントを開いて参考にしましょう。

ヒント1【コードの構成を見る】

正解のコードは上から順に以下のような構成となっています。

1.import文
 1-1. Scannerクラスのインポート
2.Mainクラスの定義
 2-1. mainメソッド
  2-1-1. Scannerオブジェクトの作成
  2-1-2. BankAccountオブジェクトの配列を3つ作成
  2-1-3. forループで各口座の名義と初期残高を入力
   2-1-3-1. 口座名義を入力
   2-1-3-2. 初期残高を入力
   2-1-3-3. 改行を消費しBankAccountオブジェクトを作成
  2-1-4. forループで各口座に対して入金および引き出しを行う
   2-1-4-1. 入金金額を入力し、depositメソッドを呼び出す
   2-1-4-2. 引き出し金額を入力し、withdrawメソッドを呼び出す
   2-1-4-3. 改行を消費
  2-1-5. forループで各口座の情報を表示
  2-1-6. BankAccountクラスの静的メソッドを呼び出して総口座数を表示
  2-1-7. Scannerオブジェクトを閉じる
3.BankAccountクラスの定義
 3-1. インスタンス変数の定義
  3-1-1. accountHolder(口座名義)
  3-1-2. balance(残高)
 3-2. クラスメンバ(静的変数)の定義
  3-2-1. totalAccounts(総口座数)
 3-3. コンストラクタの定義
  3-3-1. accountHolderとbalanceを初期化
  3-3-2. totalAccountsを1増加
 3-4. インスタンスメソッドの定義
  3-4-1. getAccountHolderメソッド
   3-4-1-1. 口座名義を返す
  3-4-2. depositメソッド
   3-4-2-1. 入金額を残高に加算
  3-4-3. withdrawメソッド
   3-4-3-1. 残高が足りる場合は引き出しを行う
   3-4-3-2. 残高が不足している場合はメッセージを表示
  3-4-4. displayAccountInfoメソッド
   3-4-4-1. 口座名義と残高を表示
 3-5. クラスメンバ(静的メソッド)の定義
  3-5-1. displayTotalAccountsメソッド
   3-5-1-1. 総口座数を表示

ヒント2【穴埋め問題にする】

以下のコードをコピーし、コメントに従ってコードを完成させて下さい。

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        // Scannerオブジェクトを作成
        Scanner scanner = new Scanner(System.in);

        // 銀行口座オブジェクトを5つ作成
        BankAccount[] accounts = new BankAccount[5];

        for (int i = 0; i < accounts.length; i++) {
            System.out.println("口座" + (i + 1) + "の名義を入力してください:");
            String accountHolder = scanner.nextLine();
            System.out.println("口座" + (i + 1) + "の初期残高を入力してください:");
            double balance = scanner.nextDouble();
            scanner.nextLine();  // 改行を消費
            accounts[i] = new BankAccount(accountHolder, balance);
        }

        // 各口座に対して入金および引き出しを行う
        for (BankAccount account : accounts) {
            System.out.println(account.getAccountHolder() + "さんの口座に入金する金額を入力してください:");
            double depositAmount = scanner.nextDouble();
            account.deposit(depositAmount);

            System.out.println(account.getAccountHolder() + "さんの口座から引き出す金額を入力してください:");
            double withdrawAmount = scanner.nextDouble();
            account.withdraw(withdrawAmount);
            scanner.nextLine();  // 改行を消費
        }

        // 各口座の情報を表示
        for (BankAccount account : accounts) {
            account.displayAccountInfo();
        }

        // 総口座数を表示
        BankAccount.displayTotalAccounts();
        
        // Scannerを閉じる
        scanner.close();
    }
}

class BankAccount {
    // インスタンス変数
    private String accountHolder;
    private double balance;
    
    // クラスメンバ(静的変数)
    private static int totalAccounts = 0;

    // コンストラクタ
    public BankAccount(String accountHolder, double balance) {
        // ***ここにaccountHolderとbalanceを初期化し、totalAccountsを1増加させるコードを書いてください***
    }

    // 口座名義を取得するメソッド
    public String getAccountHolder() {
        // ***ここに口座名義を返すコードを書いてください***
    }

    // 入金を行うメソッド
    public void deposit(double amount) {
        // ***ここに入金額を残高に加算するコードを書いてください***
    }

    // 引き出しを行うメソッド
    public void withdraw(double amount) {
        // ***ここに引き出しを行うコードを書いてください***
    }

    // 口座情報を表示するメソッド
    public void displayAccountInfo() {
        // ***ここに口座名義と残高を表示するコードを書いてください***
    }

    // 総口座数を表示する静的メソッド
    public static void displayTotalAccounts() {
        // ***ここに総口座数を表示するコードを書いてください***
    }
}

 

このヒントを見てもまだ回答を導き出すのが難しいと感じる場合は、先に正解のコードと解説を見て内容を理解するようにしましょう。

解答例

この問題の一つの正解例とそのコードの解説を以下に示します。

正解コードの例

例えば以下のようなプログラムが考えられます。

********************

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        // Scannerオブジェクトを作成
        Scanner scanner = new Scanner(System.in);

        // 銀行口座オブジェクトを5つ作成
        BankAccount[] accounts = new BankAccount[5];

        for (int i = 0; i < accounts.length; i++) {
            System.out.println("口座" + (i + 1) + "の名義を入力してください:");
            String accountHolder = scanner.nextLine();
            System.out.println("口座" + (i + 1) + "の初期残高を入力してください:");
            double balance = scanner.nextDouble();
            scanner.nextLine();  // 改行を消費
            accounts[i] = new BankAccount(accountHolder, balance);
        }

        // 各口座に対して入金および引き出しを行う
        for (BankAccount account : accounts) {
            System.out.println(account.getAccountHolder() + "さんの口座に入金する金額を入力してください:");
            double depositAmount = scanner.nextDouble();
            account.deposit(depositAmount);

            System.out.println(account.getAccountHolder() + "さんの口座から引き出す金額を入力してください:");
            double withdrawAmount = scanner.nextDouble();
            account.withdraw(withdrawAmount);
            scanner.nextLine();  // 改行を消費
        }

        // 各口座の情報を表示
        for (BankAccount account : accounts) {
            account.displayAccountInfo();
        }

        // 総口座数を表示
        BankAccount.displayTotalAccounts();
        
        // Scannerを閉じる
        scanner.close();
    }
}

class BankAccount {
    // インスタンス変数
    private String accountHolder;
    private double balance;
    
    // クラスメンバ(静的変数)
    private static int totalAccounts = 0;

    // コンストラクタ
    public BankAccount(String accountHolder, double balance) {
        this.accountHolder = accountHolder;
        this.balance = balance;
        totalAccounts++;  // 総口座数を1増加
    }

    // 口座名義を取得するメソッド
    public String getAccountHolder() {
        return accountHolder;
    }

    // 入金を行うメソッド
    public void deposit(double amount) {
        balance += amount;
    }

    // 引き出しを行うメソッド
    public void withdraw(double amount) {
        if (amount <= balance) {
            balance -= amount;
        } else {
            System.out.println("残高不足です。");
        }
    }

    // 口座情報を表示するメソッド
    public void displayAccountInfo() {
        System.out.println("口座名義: " + accountHolder + ", 残高: " + balance);
    }

    // 総口座数を表示する静的メソッド
    public static void displayTotalAccounts() {
        System.out.println("総口座数: " + totalAccounts);
    }
}

********************

コードの解説

このコードでは、Javaの「クラスメンバ」の概念を学べます。

クラスメンバはクラスの一部として定義される要素で、フィールドメソッドがあります。

これらのメンバはクラス全体に属するため、オブジェクトごとに異なる「状態」や「機能」を管理するために使用されます。

クラスの定義とインスタンス化

class BankAccount {
    private String accountHolder;
    private double balance;
    private static int totalAccounts = 0;
}

この部分では、BankAccountクラスが定義されています。

クラス内のフィールド(accountHolderbalance)は、各口座(オブジェクト)の状態を表します。

また、totalAccountsはクラスメンバで、すべてのBankAccountオブジェクト間で共通の値を保持します。

staticキーワードが付いたメンバはクラス全体で共有されるため、totalAccountsはインスタンスごとに異なるのではなく、クラス全体で一つのカウントとして管理されます。

コンストラクタとインスタンスの作成

public BankAccount(String accountHolder, double balance) {
    this.accountHolder = accountHolder;
    this.balance = balance;
    totalAccounts++;
}

コンストラクタは、新しいBankAccountオブジェクトを作成する際に呼び出されます。

ここでは、新しく作られた口座の名義と残高を設定し、totalAccountsを1増やしています。これにより、作成された総口座数が管理されます。

メソッドによる操作

public void deposit(double amount) {
    balance += amount;
}

public void withdraw(double amount) {
    if (amount <= balance) {
        balance -= amount;
    } else {
        System.out.println("残高不足です。");
    }
}

depositメソッドは、指定された金額を口座に追加する機能を持ちます。

一方、withdrawメソッドは、指定した金額を口座から引き出しますが、引き出す金額が残高より大きい場合はエラーメッセージを表示します。

クラスメンバ(静的メソッド)

public static void displayTotalAccounts() {
    System.out.println("総口座数: " + totalAccounts);
}

このdisplayTotalAccountsメソッドは、静的メソッドとして定義されており、クラス全体の総口座数を表示します。

静的メソッドはインスタンスを作成せずにクラス名を使って直接呼び出すことができ、ここではすべてのBankAccountオブジェクトで共有されるtotalAccountsにアクセスします。

まとめ

このコードでは、Javaのクラスメンバインスタンスメンバの違いを理解することができます。

クラス全体に共通する情報を管理するためにstaticキーワードを使い、個々のオブジェクトが独自の情報を持つ場合はインスタンスメンバを使います。

クラスの仕組みを正しく理解することで、より効率的なプログラミングが可能になります。

<<前の問題 問題集Top 次の問題>>

この問題への質問・コメント

この問題を作成するにあたりAIを活用しています。

問題ないことは確認していますが、もし間違いや表現の違和感などありましたら、ご指摘頂けると大変助かります。






    JAVA練習問題集へ戻る
    トップページへ戻る