クラスの基本問題


問題1

【やりたいこと】:成績を管理するために,成績クラス(Record.java)を作成したい。フィールドとして,String型の名前(name),

 点数を保持するためにint型でそれぞれ,英語(english), 国語(japanese), 数学(math)を作りたい。

【問題】:上記を実現するために,フィールドを追加した形でプログラムを作成しましょう。

【ファイル名】:Record.java


【解決方法】
下記のような形で作成します。

public class Record {
    String name;//名前を保持するフィールド
    int english;//英語の点数を保持するフィールド
    int japanese;//国語の点数を保持するフィールド
    int math;//数学の点数を保持するフィールド
}

【解説】
クラスとして,Record.javaを新規に作成して,フィールドをそれぞれ追加します。
※アクセス修飾子については,今回の場合,なんでもかまいません。
このRecordクラスは,他のクラスから利用するために作成したものなので,mainメソッドは含めません。

【スッキリわかるJava入門編第2版の参考ページ】307-309ページ


問題2

【やりたいこと】:問題1で作成したRecordクラスに,引数ありのコンストラクタを用意して,名前とそれぞれの点数を設定したい。

【問題】:上記を実現するために,引数ありのコンストラクタを追加した形でプログラムを作成しましょう。

     デフォルトコンストラクタには何も設定しなくて大丈夫です。

【ファイル名】:Record.java


【解決方法】
下記のような形で作成します。

public class Record {
    String name;//名前を保持するフィールド
    int english;//英語の点数を保持するフィールド
    int japanese;//国語の点数を保持するフィールド
    int math;//数学の点数を保持するフィールド

    Record() {

    }

    Record(String name, int english, int japanese, int math) {
        this.name = name;
        this.english = english;
        this.japanese = japanese;
        this.math = math;
    }
}

【解説】
デフォルトコンストラクタには,何も定義しない形で作成します。
引数ありのコンストラクタ側では,引数に渡された値をフィールドに合わせて,設定します。
引数ありのコンストラクタを利用することで,インスタンス化すると同時にフィールドへ値を設定できます。

【スッキリわかるJava入門編第2版の参考ページ】347-360ページ


問題3

【やりたいこと】:問題2で作成したRecordクラスに,合計点を返すメソッド(sum),平均点を返すメソッド(avg)を作成したい。

【問題】:上記を実現するために,合計点を返すメソッド(引数なし,戻り値int),平均点を返すメソッド(引数なし,戻り値double)を作成しましょう。

【ファイル名】:Record.java


【解決方法】
下記のような形で作成します。

public class Record {
    String name;//名前を保持するフィールド
    int english;//英語の点数を保持するフィールド
    int japanese;//国語の点数を保持するフィールド
    int math;//数学の点数を保持するフィールド

    Record() {

    }

    Record(String name, int english, int japanese, int math) {
        this.name = name;
        this.english = english;
        this.japanese = japanese;
        this.math = math;
    }

    public int sum() {
        return this.english + this.japanese + this.math;
    }

    public double avg() {
        double result = (double) sum() / 3;
        return result;
    }
}

【解説】
合計を求めるメソッド(sum)は,フィールドの英語,国語,数学の点数を足して戻すだけで完了です。
平均を求めるメソッド(avg)は,合計値から科目数の3で割ることで計算結果は求められますが,
合計値はsumメソッドを呼び出し,戻り値をdoubleで返す必要がありますので,(double)のキャストを追加して,
型をdouble型に変更してから計算をすることで,戻り値をdoubleへと変換しています。

【スッキリわかるJava入門編第2版の参考ページ】75-83, 307-313ページ


問題4

【やりたいこと】:問題3で作成したRecordクラスに,名前や点数,合計などを表示するメソッドを作成したい。

【問題】:上記を実現するために,データを表示するdisplayメソッド(引数なし,戻り値なし)を作成しましょう。

【ファイル名】:Record.java

displayメソッドを呼び出した場合は,下記のように出力しましょう。(名前:Bebeit,英語:70,国語:80,数学:90と設定されている前提です。)

名前:Bebeit
英語:70
国語:80
数学:90
合計点:240
平均点:80.0
-------------------------

【解決方法】
下記のような形で作成します。

public class Record {
    String name;//名前を保持するフィールド
    int english;//英語の点数を保持するフィールド
    int japanese;//国語の点数を保持するフィールド
    int math;//数学の点数を保持するフィールド

    Record() {

    }

    Record(String name, int english, int japanese, int math) {
        this.name = name;
        this.english = english;
        this.japanese = japanese;
        this.math = math;
    }

    public int sum() {
        return this.english + this.japanese + this.math;
    }

    public double avg() {
        double result = (double) sum() / 3;
        return result;
    }

    public void display() {
        System.out.println("名前:" + this.name);
        System.out.println("英語:" + this.english);
        System.out.println("国語:" + this.japanese);
        System.out.println("数学:" + this.math);
        System.out.println("合計点:" + sum());
        System.out.println("平均点:" + avg());
        System.out.println("-------------------------");
    }
}

【解説】
displayメソッドでは,フィールドの値をそれぞれ表示する形にして,合計点と平均点については,メソッドを利用して出力を作ります。
staticのついていないメソッドはインスタンスメソッドとも呼ばれ,インスタンスで設定されているフィールドをメソッド内で利用できます。
身近なものをクラスに置き換えてみて,色々なプログラムを書いて慣れていきましょう。

【スッキリわかるJava入門編第2版の参考ページ】307-313ページ


問題5

【やりたいこと】:問題4で作成したRecordクラスをインスタンス化して,フィールドの情報を表示したい。

【問題】:上記を実現するために,Main.javaクラスで,インスタンスを作成し,displayメソッドを呼び出しましょう。

【ファイル名】:Main.java

displayメソッドを呼び出した場合は,下記のように出力しましょう。(名前:Bebeit,英語:70,国語:80,数学:90と設定されている前提です。)

名前:Bebeit
英語:70
国語:80
数学:90
合計点:240
平均点:80.0
-------------------------

【解決方法】
下記のような形で作成します。

public class Main {
    public static void main(String[] args) {
        Record rec = new Record("Bebeit", 70, 80, 90);
        rec.display();
    }
}

【解説】
インスタンス化をする場合,newのキーワードとともに,コンストラクタを呼び出します。
今回の場合,フィールドに値を設定する場合,コンストラクタを利用することで,シンプルにまとめることができます。
引数の順番を間違えないようにして,値を設定し,recの変数にインスタンスを代入します。
最後にフィールドの情報を出力するために,displayメソッドを呼び出す記述をします。

【スッキリわかるJava入門編第2版の参考ページ】317-325ページ


問題6

【やりたいこと】:問題4で作成したRecordクラスに,クラス変数(静的メンバ,静的フィールドとも言う)countを追加して,インスタンスが

         作成された数を保持したい。

【問題】:上記を実現するために,Recordクラスにクラス変数countを追加して,インスタンスが作成されるたびにcountを加算しましょう。

【ファイル名】:Record.java


【解決方法】
下記のような形で作成します。

public class Record {
    String name;//名前を保持するフィールド
    int english;//英語の点数を保持するフィールド
    int japanese;//国語の点数を保持するフィールド
    int math;//数学の点数を保持するフィールド
    static int count = 0;//①インスタンスが作成された数を保持するクラス変数

    Record() {
        count++;//②インスタンスが作成された時にcountを増やす
    }

    Record(String name, int english, int japanese, int math) {
        this.name = name;
        this.english = english;
        this.japanese = japanese;
        this.math = math;
        count++;//③インスタンスが作成された時にcountを増やす
    }

    public int sum() {
        return this.english + this.japanese + this.math;
    }

    public double avg() {
        double result = (double) sum() / 3;
        return result;
    }

    public void display() {
        System.out.println("名前:" + this.name);
        System.out.println("英語:" + this.english);
        System.out.println("国語:" + this.japanese);
        System.out.println("数学:" + this.math);
        System.out.println("合計点:" + sum());
        System.out.println("平均点:" + avg());
        System.out.println("-------------------------");
    }
}

【解説】
クラス変数は,フィールドの修飾子としてstaticがつきます。staticがついているフィールドは,クラスに一つだけという変数になります。
インスタンスフィールドは,インスタンスごとに変数を持ちますが,クラス変数は,クラスに1個しかありません。
今回の場合,インスタンス化されるたびに,クラス変数のcountを加算することで,インスタンス化された数をカウントしています。

【スッキリわかるJava入門編第2版の参考ページ】361-366ページ


問題7

【やりたいこと】:問題6で作成したRecordクラスに,クラスメソッド(静的メソッドとも言う)maxを追加して,2つのインスタンスを引数に

         渡して合計点の大きい方を戻り値とするメソッドを作成したい。

【問題】:上記を実現するために,Recordクラスにクラスメソッドmax(第一引数Record, 第二引数Record,戻り値Record)を追加して,

     合計点が大きいRecordのインスタンスを戻り値にしてください。

     ただし,合計点数が同じ場合は,第一引数のRecordを返してください。

【ファイル名】:Record.java


【解決方法】
下記のような形で作成します。

public class Record {
    String name;//名前を保持するフィールド
    int english;//英語の点数を保持するフィールド
    int japanese;//国語の点数を保持するフィールド
    int math;//数学の点数を保持するフィールド
    static int count = 0;//インスタンスが作成された数を保持するクラス変数

    Record() {
        count++;//インスタンスが作成された時にcountを増やす
    }

    Record(String name, int english, int japanese, int math) {
        this.name = name;
        this.english = english;
        this.japanese = japanese;
        this.math = math;
        count++;//インスタンスが作成された時にcountを増やす
    }

    public int sum() {
        return this.english + this.japanese + this.math;
    }

    public double avg() {
        double result = (double) sum() / 3;
        return result;
    }

    public void display() {
        System.out.println("名前:" + this.name);
        System.out.println("英語:" + this.english);
        System.out.println("国語:" + this.japanese);
        System.out.println("数学:" + this.math);
        System.out.println("合計点:" + sum());
        System.out.println("平均点:" + avg());
        System.out.println("-------------------------");
    }

    public static Record max(Record rec1, Record rec2) {
        if (rec1.sum() >= rec2.sum()) {
            return rec1;
        } else {
            return rec2;
        }
    }
}

【解説】
クラスメソッドは,メソッドの修飾子としてstaticがつきます。staticがついているメソッドは,クラスに一つだけというメソッドになります。
インスタンスメソッドは,インスタンスごとの変数を持ちいて処理をしますが,クラスメソッドは,インスタンス化せずに,
クラス名.メソッド名 という形で利用ができます。
今回の場合,与えられたRecordのインスタンスごとにsumメソッドを利用して合計を取得してそちらを比較して,結果を返しています。

【スッキリわかるJava入門編第2版の参考ページ】367-369ページ


問題8

【やりたいこと】:問題7で作成したRecordクラスにて,2つのインスタンスを作成して,合計点数の高い方のフィールドの情報を表示したい。

【問題】:上記を実現するために,Main.javaクラスで,2つのインスタンスを作成し,合計点数の高い方でdisplayメソッドを呼び出しましょう。

【ファイル名】:Main.java

たとえば2つのインスタンスが次のように設定されている場合は,下記のように出力しましょう。

(1人目,名前:Bebeit,英語:70,国語:80,数学:90)

(2人目,名前:たろう,英語:75,国語:85,数学:95)

名前:たろう
英語:75
国語:85
数学:95
合計点:255
平均点:85.0
-------------------------

【解決方法】
下記のような形で作成します。

public class Main {
    public static void main(String[] args) {
        Record rec = new Record("Bebeit", 70, 80, 90);
        Record rec2 = new Record("たろう", 75, 85, 95);

        Record.max(rec, rec2).display();
    }
}

【解説】
インスタンスを2つ例にあわせて作成をします。
次に合計点数の高い方を返すクラスメソッドのmaxを利用して,合計点数の高いインスタンスを受けとり,それに対してdisplayメソッドを呼び,
フィールドの情報を出力しています。6行目の処理は,上記の説明を順に実行している形で一行でまとめています。
Record.max(rec, rec2)を処理することで,戻り値として,rec2が戻ってくるため, rec2.display()を呼び出していると考えることができます。
少しずつなれてくることで,ある程度まとめて処理を簡潔に記述できるようになってきますので,少しずつ慣れていきましょう。

【スッキリわかるJava入門編第2版の参考ページ】332-370ページ


問題9

【やりたいこと】:Humanクラスを定義して,引数ありコンストラクタを用いてフィールドの初期化をしたい。

【問題】:現在のHumanクラスのコンストラクタではフィールドに値の設定ができませんでした。どのように修正すればよいでしょうか?

【ファイル名】:Human.java

public class Human {
    String name;//名前
    int age;//年齢
    double weight;//体重
    double height;//身長

    Human(String name, int age, double weight, double height){
        name = name;
        age = age;
        weight = weight;
        height = height;
    }
}

【解決方法】
下記のような形で作成します。

public class Human {
    String name;//名前
    int age;//年齢
    double weight;//体重
    double height;//身長

    Human(String name, int age, double weight, double height) {
        this.name = name;
        this.age = age;
        this.weight = weight;
        this.height = height;
    }
}

【解説】
8, 9, 10, 11行目に同じような警告内容で,「変数●●の代入は無効です」となっているかと思います。
問題の場合の記述の仕方だと,フィールド名と引数の名前が同じなので,フィールドと引数の違いを表すためにthis.が必要になります。
フィールドなどにアクセスする場合のthisは省略可能なこともありますが,省略せずに明示的に記載するようにしましょう。

【スッキリわかるJava入門編第2版の参考ページ】307-313ページ


問題10

【やりたいこと】:Humanクラスに引数なしコンストラクタを作成したい。ただし,引数なしコンストラクタの中で,引数ありコンストラクタを         呼び出して設定したい。

【問題】:現在のHumanクラスの引数ありコンストラクタを利用して,引数なしコンストラクタを呼び出す場合,どのように修正すればよいで      しょうか?引数なしコンストラクタが呼ばれた場合,名前:たろう,年齢:6,身長:116, 体重:21 と設定してください。

【ファイル名】:Human.java

public class Human {
    String name;//名前
    int age;//年齢
    double weight;//体重
    double height;//身長

    Human(String name, int age, double weight, double height) {
        this.name = name;
        this.age = age;
        this.weight = weight;
        this.height = height;
    }

    Human() {
        //ここに回答をお願いします。
    }
}

【解決方法】
下記のような形で作成します。

public class Human {
    String name;//名前
    int age;//年齢
    double weight;//体重
    double height;//身長

    Human(String name, int age, double weight, double height) {
        this.name = name;
        this.age = age;
        this.weight = weight;
        this.height = height;
    }

    Human() {
        this("たろう", 6, 116.0, 21.0);
    }
}

【解説】
コンストラクタの中から別のコンストラクタを呼ぶことで,フィールドの値を設定することができます。
コンストラクタ内から別のコンストラクタを呼ぶ場合,thisを利用します。
上記の場合,引数なしコンストラクタを呼ぶと,その中に記述されている引数ありコンストラクタを呼び出しています。

【スッキリわかるJava入門編第2版の参考ページ】355-360ページ


問題11

【やりたいこと】:Humanクラスに引数なしコンストラクタを作成したい。ただし,引数なしコンストラクタの中で,引数ありコンストラクタを         呼び出して設定したい。

【問題】:現在の書き方だとエラーがでています。何が原因でどのように修正すればよいでしょうか?

【ファイル名】:Human.java

public class Human {
    String name;//名前
    int age;//年齢
    double weight;//体重
    double height;//身長

    Human(String name, int age, double weight, double height) {
        this.name = name;
        this.age = age;
        this.weight = weight;
        this.height = height;
    }

    void Human() {
        this("たろう", 6, 116.0, 21.0);
    }
}

【解決方法】
下記のような形で作成します。

public class Human {
    String name;//名前
    int age;//年齢
    double weight;//体重
    double height;//身長

    Human(String name, int age, double weight, double height) {
        this.name = name;
        this.age = age;
        this.weight = weight;
        this.height = height;
    }

    Human() {
        this("たろう", 6, 116.0, 21.0);
    }
}

【解説】
15行目でエラーがでており,「コンストラクター呼び出しは、コンストラクター内の最初のステートメントである必要があります」
のようなメッセージがでていることがわかります。
コンストラクタの条件としては,①クラス名と同じ名前②戻り値に当たる記述をいれてはいけない。が満たされていないといけません。
上記の問題のコードでは,メソッドと判定されているため,上記のエラーメッセージが表示されてしまうので,
コンストラクタの記述方法にあわせて修正をします。

【スッキリわかるJava入門編第2版の参考ページ】352ページ


問題12

【やりたいこと】:Humanクラスのフィールドすべてをカプセル化したい。

【問題】:問題11で完成したHumanクラスのフィールドをカプセル化するにはどうしたらよいでしょうか?

【ファイル名】:Human.java


【解決方法】
下記のような形で作成します。

public class Human {
    private String name;//名前
    private int age;//年齢
    private double weight;//体重
    private double height;//身長

    Human(String name, int age, double weight, double height) {
        this.name = name;
        this.age = age;
        this.weight = weight;
        this.height = height;
    }

    Human() {
        this("たろう", 6, 116.0, 21.0);
    }
}

【解説】
カプセル化をするため,フィールドにアクセス修飾子のprivate を追加します。
外部のクラスから値を直接変更させないための機能となります。

【スッキリわかるJava入門編第2版の参考ページ】374-382ページ


問題13

【やりたいこと】:Humanクラスにゲッターセッターを作りたい。

【問題】:問題12で完成したHumanクラスのフィールドに対して,ゲッターセッターを追加するにはどうしたらよいでしょうか?

【ファイル名】:Human.java


【解決方法】
下記のような形で作成します。

public class Human {
    private String name;//名前
    private int age;//年齢
    private double weight;//体重
    private double height;//身長

    Human(String name, int age, double weight, double height) {
        this.name = name;
        this.age = age;
        this.weight = weight;
        this.height = height;
    }

    Human() {
        this("たろう", 6, 116.0, 21.0);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getWeight() {
        return weight;
    }

    public void setWeight(double weight) {
        this.weight = weight;
    }

    public double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }
}

【解説】
それぞれのフィールドに対して,ゲッターセッターを作ります。
ゲッターは,get + フィールド名,セッターは, set + フィールド名 として,区切りの単語の最初の一文字を大文字にします。
ゲッターはフィールドの値を取得するためのメソッドで,セッターはフィールドの値を設定するためのメソッドとなります。
これらを用意することによって,外部クラスからでも,フィールドの変更ができるようになります。

【スッキリわかるJava入門編第2版の参考ページ】385-393ページ


問題14

【やりたいこと】:Humanクラスのセッターを利用して,フィールドに値を設定したい。

【問題】:問題13で完成したHumanクラスを利用して,Main.javaにて,フィールドに値を設定するにはどうしたらよいでしょうか?

【ファイル名】:Main.java

public class Main {
    public static void main(String[] args) {
        Human hanako = new Human();
        //セッターを利用して,名前:はなこ,年齢:6才,身長:112.7cm,体重:19.6kgを設定しましょう。

    }
}

【解決方法】
下記のような形で作成します。

public class Main {
    public static void main(String[] args) {
        Human hanako = new Human();
        //セッターを利用して,名前:はなこ,年齢:6才,身長:112.7cm,体重:19.6kgを設定しましょう。
        hanako.setName("はなこ");
        hanako.setAge(6);
        hanako.setHeight(112.7);
        hanako.setWeight(19.6);
    }
}

【解説】
カプセル化によりフィールドがprivateとなっているため,セッターを利用してでないとフィールドへ値を設定が出来ない状態になっています。
セッターを利用して,フィールドに値を設定するには上記のような記述で順に値を設定します。
あらかじめ入力データがすべて決まっている場合は,引数ありコンストラクタを利用して設定する形にするとシンプルにまとめられます。
今回は,セッターの利用の仕方を学ぶという問題になります。

【スッキリわかるJava入門編第2版の参考ページ】389-393ページ


問題15

【やりたいこと】:Humanクラスのゲッターを利用して,フィールドの値を出力したい。

【問題】:問題13で完成したHumanクラスを利用して,Main.javaにて,フィールドの値を取得するにはどうしたらよいでしょうか?

【ファイル名】:Main.java

public class Main {
    public static void main(String[] args) {
        Human hanako = new Human("はなこ", 6, 112.7, 19.6);
        //ゲッターを利用して,フィールドの値を取得して出力しましょう。
        String name = ???;//名前を取得しましょう。
        int age = ???;//年齢を取得しましょう。
        double height = ???;//身長を取得しましょう。
        double weight = ???;//体重を取得しましょう。
        System.out.println("名前:" + name);
        System.out.println("年齢:" + age);
        System.out.println("身長:" + height);
        System.out.println("体重:" + weight);
    }
}

【解決方法】
下記のような形で作成します。

public class Main {
    public static void main(String[] args) {
        Human hanako = new Human("はなこ", 6, 112.7, 19.6);
        //ゲッターを利用して,フィールドの値を取得して出力しましょう。
        String name = hanako.getName();//名前を取得しましょう。
        int age = hanako.getAge();//年齢を取得しましょう。
        double height = hanako.getHeight();//身長を取得しましょう。
        double weight = hanako.getWeight();//体重を取得しましょう。
        System.out.println("名前:" + name);
        System.out.println("年齢:" + age);
        System.out.println("身長:" + height);
        System.out.println("体重:" + weight);
    }
}

【解説】
カプセル化によりフィールドがprivateとなっているため,ゲッターを利用してでないとフィールドの値を取得が出来ない状態になっています。
ゲッターを利用して,フィールドの値を取得するには上記のような記述で順に値を設定します。
今回は,ゲッターの利用の仕方を学ぶという問題になります。

【スッキリわかるJava入門編第2版の参考ページ】385-388ページ