質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.92%

privateのフィールドに外部クラスからアクセスする

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 3,465
退会済みユーザー

退会済みユーザー

 前提・実現したいこと

こんばんは、Javaについての質問です。
とあるJavaの問題を解いていて、ある程度自力で調べてはみたものの、どうしても分からず困っています。
お助け願います…
下記が問題文となります。

 問題文

下記クラスにあるフィールドをprivateにした上で、外部から値を設定したり取得できるように変更しなさい。
ただしhour0~23,minute0~59,second0~59の間の値しか設定できないように制限すること。
それ以外の値を設定しようとした場合のエラー文言は任意とする。

使用前提条件のクラス:

public class Clock{
    int hour;
    int minute;
    int second;
}

 作成途中のソースコード

// Clockクラス //

public class Clock {
        private int hour;
        private int minute;
    private int second;

     //コンストラクタ
        Clock(int hour, int minute, int second){  
                this.hour = hour;
                this.minute = minute;
                this.second = second;
        }

        //SET
         public void setHour(int hour) {
             this.hour = hour;
        }

        public void setMinute(int minute) {
            this.minute = minute;
        }

        public void setSecond(int second) {
            this.second = second;
        }

        //GET
        public int getHour(){
            return hour;
        }

        public int getMinute(){
            return minute;
        }

        public int getSecond(){
            return second;
        }

}


// Clockクラスを外部から実行するための別クラス、ClockTestクラス //


import java.io.*;

public class ClockTest {
    public static void main(String[] args) throws IOException {

    try{
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

        Clock clock = new Clock(); 

        System.out.print("数値を入力してください>" + " ");
        String str = br.readLine();

        clock.setHour() = Integer.parseInt(str);
        clock.setMinute() = Integer.parseInt(str);
        clock.setSecond() = Integer.parseInt(str);

        // 範囲チェック
        if ((clock.getHour() > 0) && (clock.getHour() <= 23)) {
            System.out.println(clock.getHour());

        } else if ((clock.getMinute() > 0) && (clock.getMinute() <= 59)) {
            System.out.println(clock.getMinute());

        } else if ((clock.getSecond() > 0) && (clock.getSecond() <= 59)) {
            System.out.println(clock.getSecond());
        }

        } catch(Exception e) {
            System.out.print("[ERROR] 数値を再入力してください>" + " ");
        }

    }
}

 制作途中のソースコードの改善(再度修正)

// Clockクラス //

public class Clock {
        private int hour;
        private int minute;
    private int second;

    //コンストラクタ1
     public Clock(){
         super();
        }

     //コンストラクタ2
        Clock(int hour, int minute, int second){
                this.hour = hour;
                this.minute = minute;
                this.second = second;
        }

        //SET
         public void setHour(int hour) {
             if(hour > 0 && hour <= 23){
             this.hour = hour;
         /*
             } else {
            System.out.println("[ERROR] 数値を再入力してください");
        }
               */
        }

        public void setMinute(int minute) {
            if(minute > 0 && minute <= 59){
            this.minute = minute;
         /*
            } else {
            System.out.println("[ERROR] 数値を再入力してください");
        }
               */
        }

        public void setSecond(int second) {
            if(second > 0 && second <= 59){
            this.second = second;
         /*
            } else {
            System.out.println("[ERROR] 数値を再入力してください");
        }
               */
        }

        //GET
        public int getHour(){
            return hour;
        }

        public int getMinute(){
            return minute;
        }

        public int getSecond(){
            return second;
        }

}



// Clockクラスを外部から実行するための別クラス、ClockTestクラス //


import java.io.*;

public class ClockTest {
    public static void main(String[] args) throws IOException {


        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        Clock clock = new Clock();

/*
        System.out.print("数値を入力してください>" + " ");
        String str = br.readLine();

        clock.setHour(Integer.parseInt(str));
        clock.setMinute(Integer.parseInt(str));
        clock.setSecond(Integer.parseInt(str));
*/

//冗長かもしれませんが、入力の仕方を一つずつ入力できるよう修正しました

       System.out.print("hourの数値を入力してください>" + " ");
        String str = br.readLine();
        clock.setHour(Integer.parseInt(str));

        System.out.print("minuteの数値を入力してください>" + " ");
        str = br.readLine();
        clock.setMinute(Integer.parseInt(str));

        System.out.print("secondの数値を入力してください>" + " ");
        str = br.readLine();
        clock.setSecond(Integer.parseInt(str));

        try{
            System.out.println("hour" + " " + clock.getHour());
            System.out.println("minute" + " " + clock.getMinute());
            System.out.println("second" + " " + clock.getSecond());

        } catch(Exception e) {
            System.out.println("[ERROR] 数値を再入力してください");
        }

    }
}

 やりたいこと、困っていること

実行(したい)画面例

hourの数値を入力してください> 100
[ERROR]数値を再入力してください> 23
hour 23
minuteの数値を入力してください> 12
minute 12
secondの数値を入力してください> 36
second 36

現状、このプログラムをコンパイルしようとすると、インスタンス化ができませんというエラーと、clock.setHourに引数がありませんというエラーが出てしまい、実行できません。
実現したいこととしては、キーボードから好きな数値を入力させ、入力値が指定した数値の範囲内であれば出力し次の入力へ、範囲外であればエラー文言を出力、再入力を求めるプログラムを作成したいのですが、setとgetの使い方をうまく理解できていないせいかここから進まず…基礎の話で申し訳ないのですが、ご助言等いただけますと幸いです。
問題文には明記されていませんが、条件としてsetとgetを必ず使用することとなっています。
お手数おかけいたしますが何卒よろしくお願いいたします。

 やりたいこと、困っていること(追記)

少し考えてみて、編集し直してみました。エラーは起こらなくなり、setでの値の設定も恐らく正しく行えたはずですので、プログラムの完成に少し近づけた気がします。
しかし、現状値を一つ入力すると、実行画面が下記のように出力されてしまいます。

数値を入力してください> 24
[ERROR] 数値を再入力してください
hour 0
minute 24
second 24

一度入力した数値が全ての値の範囲内であれば、全て入力されてしまいます…。恐らくは再入力を求める繰り返し文の設定を行なっていない為だと思うのですが、またここからどうしていいのか、お力を貸していただけると助かります。
お手数おかけいたしますが、引き続き何卒よろしくお願いいたします。

 補足情報(FW/ツールのバージョンなど)

Java
java version "1.8.0_161"

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+4

質問する際には、必ず実際のエラーメッセージを載せるようにしてください。

インスタンス化ができませんというエラー

Clockをインスタンス化するときに適切な引数を与えていないのが原因です。

Clockのコンストラクタの定義

Clock(int hour, int minute, int second){  
    this.hour = hour;
    this.minute = minute;
    this.second = second;
}

こちらでは、int型の引数をみっつ受け取るようなインターフェースになっています。

実際にインスタンス化を試みている箇所

Clock clock = new Clock();

しかし、実際には引数が与えられていません。これが問題です。

解消するためには

次の二つのアプローチが考えられます。

  • インスタンス生成時に、適切な引数を渡すようにすること
  • 引数なしのコンストラクタを用意し、各フィールドを適切に初期化すること

clock.setHourに引数がありませんというエラー

同じように、メソッドのインターフェースに沿った呼び出しがされていないからです。

Clock#setHourの定義

public void setHour(int hour) {
    this.hour = hour;
}

int型の引数をひとつだけ受け取るように書かれています。

実際にメソッドを呼び出そうとしている箇所

clock.setHour() = Integer.parseInt(str);

これは完全に使い方を誤っていますね。
セッターと言えど、その実態はふつうのメソッドと一緒です。

解消するためには

Integer.parseInt(str)の結果を、メソッドの引数として渡してやればいいです。

clock.setHour(Integer.parseInt(str));

冗長な感がありますが、二行に分けて書くことも出来ます。

int hour = Integer.parseInt(str);
clock.setHour(hour);

hourは0~23,minuteは0~59,secondは0~59の間の値しか設定できないように制限すること。

これはとりあえずコンパイルエラーを排除してから考えましょう。
いちおうヒントとしては、『セッターの中で値をチェックすれば良い』とだけ言っておきます。

質問追記を受けて

一度入力した数値が全ての値の範囲内であれば、全て入力されてしまいます…。

単に入力を一度しか受け付けていないからかと。

System.out.print("数値を入力してください>" + " ");
String str = br.readLine();

clock.setHour(Integer.parseInt(str));
clock.setMinute(Integer.parseInt(str));
clock.setSecond(Integer.parseInt(str));

時/分/秒について、それぞれ入力を求めるように書き直せば良いんじゃないでしょうか。


もし例外を使うならこんな感じです。

class Clock {
    ...

    public void setHour(int hour) {
         if(hour > 0 && hour <= 23){
             this.hour = hour;
         } else {
             throw new IllegalArgumentException();
         }
    }

    ...
}
while(true){
    try{
        System.out.print("hourの数値を入力してください>" + " ");
        String str = br.readLine();
        clock.setHour(Integer.parseInt(str));
    }catch(IllegalArgumentException e){
        System.err.println("[ERROR] 数値を再入力してください");
    }
}

もし返り値を使うならこんな感じです。

class Clock {
    ...

    public boolean setHour(int hour) {
         if(hour > 0 && hour <= 23){
             this.hour = hour;
             return true;
         } else {
             return false;
         }
    }

    ...
}
while(true){
    try{
        System.out.print("hourの数値を入力してください>" + " ");
        String str = br.readLine();

        boolean result = clock.setHour(Integer.parseInt(str));
        if(result) {
            break;
        } else {
            System.err.println("[ERROR] 数値を再入力してください");
        }
    }catch(NumberFormatException e){
         System.err.println("[ERROR] 数値を再入力してください");
    }
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/28 00:43

    Clockクラスも少々変更したため、こちらに掲載させていただきます。やや見辛くなってしまって申し訳ありません。修正したコードは下記の通りとなります。

    // Clockクラス

    public class Clock {
    private int hour;
    private int minute;
    private int second;

    //コンストラクタ1
    public Clock(){
    super();
    }

    //コンストラクタ2
    Clock(int hour, int minute, int second){
    this.hour = hour;
    this.minute = minute;
    this.second = second;
    }

    //SET
    public void setHour(int hour) {
    if(hour > 0 && hour <= 23){
    this.hour = hour;
    }
    }

    public void setMinute(int minute) {
    if(minute > 0 && minute <= 59){
    this.minute = minute;
    }
    }

    public void setSecond(int second) {
    if(second > 0 && second <= 59){
    this.second = second;
    }
    }

    //GET
    public int getHour(){
    return hour;
    }

    public int getMinute(){
    return minute;
    }

    public int getSecond(){
    return second;
    }

    }

    キャンセル

  • 2018/05/28 12:30

    回答にイメージを追記しておきました。

    キャンセル

  • 2018/05/28 23:15

    返信遅くなりました。
    コードのイメージの追記をいただき、ありがとうございます。
    返り値のイメージの方を元に修正したところ、行いたかったこと通りの動作ができました!
    沢山お聞きしてしまったのに、最後までお付き合いいただけて本当にありがとうございます。また一つ勉強になりました。
    根気強く面倒見てくださったLouiS0616さんにベストアンサーをお贈りいたします、改めましてありがとうございました!

    キャンセル

+1

こんにちは、
引数が時、分、秒であるクラスにしました。
時、分、秒をそれぞれ入力し、それをもとに時刻を表示します。

 質問欄にあるソースコードを見て気になったところ

       if ((clock.getHour() > 0) && (clock.getHour() <= 23)) {
            System.out.println(clock.getHour());

        } else if ((clock.getMinute() > 0) && (clock.getMinute() <= 59)) {
            System.out.println(clock.getMinute());

        } else if ((clock.getSecond() > 0) && (clock.getSecond() <= 59)) {
            System.out.println(clock.getSecond());
        }


とありますが、else ifではなくすべてただのifです。
例えば、「時」を入力するとき12を入力すると最初のif文はになるので、それ以降のelse ifは実行されません。

私が書いたコードでは配列とfor文を使ったループ処理で判定を行っています。

import java.io.*;
import java.util.*;

public class Midi{ 
    public static void main(String[] args) throws IOException {

        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

        try{

             String []text = {"hour","minute","second"};
             int []limit = {24,60,60};
             int []time = new int[3];
             boolean []judge = new boolean[3];

             for(int i = 0; i < time.length; i++){
                 System.out.println(text[i] + "の数字を入力してください。");
                 do{
                     String str = br.readLine();
                     time[i] = Integer.parseInt(str);
                     if(0 <= time[i] && time[i] < limit[i]){
                         judge[i] = false;
                     }
                     else{
                         judge[i] = true;
                         System.out.println("再入力してください。");
                     }
                 }while(judge[i]);
             }


             Clock clock = new Clock(time[0],time[1],time[2]); 
             clock.print_time();

        }
        catch(InputMismatchException e){
            System.out.println("数字を入力してください。");
        }
    }
}

class Clock{

    private int hour;
    private int minute;
    private int second;

    public Clock(int Hour, int Minute, int Second){
        this.hour = Hour;
        this.minute = Minute;
        this.second = Second;
    }
    public void print_time(){
        System.out.println(hour + "時" + minute + "分"  + second + "秒");
    }
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/27 22:44

    確認、返信が遅くなってしまい申し訳ございません。
    ご丁寧な回答ありがとうございます。こういった記述の仕方もあるのだとまたひとつ勉強になりました、毎回ご回答いただきまして大変助かります。今後の参考にさせていただきます。ありがとうございます…!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.92%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る