第4講:もっともシンプルな「時間割表示システム」を拡張する

その2 「授業の情報」のキーボード入力を受付させる(2)

 先ほど学んだ「BufferedReaderクラス」の使い方と、「入力エラーへの対処」を利用してまず最初に「ClassInfo.java」を「授業の情報」のキーボード入力を受け付けるように改造します。そしてつぎに、この処理の手順を参考にしながら「ClassTable.java」に「授業の情報」をキーボードから入力させるメソッドを記述します。

(1)「ClassInfo.java」をキーボード入力を受け付けるように改造する

 これまでの「ClassInfo」クラスはユーザー自身が起動する(つまりメイン・メソッドを持った)プログラムでしたこちらを参照)。このプログラムにおいては、今のところ「1、情報処理、i308」と「2、民法、e307」という二つの「授業の情報」が代入文として直接書き込まれており、それらがディスプレイに表示されるようになっていました。

 いまここで、このプログラムを「キーボードから入力された「授業の情報」をディスプレイにそのまま表示するプログラム」として書き換えることにします。

 以下に表示される「ClassInfo」の緑色のコメントの部分に先ほど学習した「BufferedReaderクラス」を利用する命令を記入してゆきます。「エラーへの対処」はあらかじめ記入してあります(青字)ので書式を確認して下さい。ただし2カ所だけ注意の必要な部分があります(赤字)。この部分の説明をつぎに行います。

/* キーボードから読み込んだ2回分の
 「授業の情報」を表示するプログラム*/

// 入出力関連パッケージの利用を宣言する

public class ClassInfo {
	public static void main(String args[]){

		try{

			/*「ClassTable」を利用して2つの「授業の情報」を作る*/
			ClassTalbe info1 = new ClassTable();	// 「info1」を作る
			ClassTalbe info2 = new ClassTable();	// 「info2」を作る

			/*「BufferedReader」をインスタンス化する*/

			/* readLine()メソッドを利用して2つの「授業の情報」の
			 内容をキーボードから読み込む*/
			// 「info1」の「時限」に内容を読み込む
			// 「info1」の「科目名」に内容を読み込む
			// 「info1」の「教室名」に内容を読み込む

			// 「info2」の「時限」に内容を読み込む
			// 「info2」の「科目名」に内容を読み込む
			// 「info2」の「教室名」に内容を読み込む

			/*2つの「授業の情報」の内容をディスプレイに表示する*/
			info1.showData();		// 「info1」の内容を表示する
			info2.showData();		// 「info2」の内容を表示する

		}// 例外への対処;エラーメッセージを表示してプログラムを終了する
		catch( Exception e ){ System.out.println("エラーが発生しました。");}

	}
}

 赤字で示された行には、「readLineメソッド」を利用してキーボードから「時限」を読み込みます。ただし注意しなければならないのは、「 readLineメソッド」の返値は常に「文字列型(String)」であるのに対し、代入分の左辺に用意されているのは「整数型(int)」の変数として登録された「ClassTableクラス」の属性「no」です。仮にそのままユーザーがキーボードから「1」と入力したとしても、読み込まれてくるのは「文字列型」に属する「1」という文字です。すこしややこしいのですが、プログラムにおいては「文字列型」の「1」と「整数型」の「1」が別々に存在するのです。そして、「型」の異なる値を変数に代入することはできないのです。

 そこで、「文字列型」に属する数字を「整数型」に変換してくれる便利なメソッドを利用してこの問題を解決することにします。

Integer.parseInt( 文字列型に属する数字)

 これは、「Integerクラス」に属する「parseInt」メソッドです。このメソッドの()内に変換してほしい「文字列型に属する数字」を記入します。すると返値として、その数字を「整数型」に変換した値を返してくれます。このメソッドはインスタンスを作らずに直接クラス名「Integer」で呼び出します。

 ところで、このメソッドのように、メソッド名の次にある()内に処理を行う際に必要な情報を記入しなければならない場合が多々あります。このメソッドの外部からメソッドに対して渡す値のことを「引数」といいます。メソッドに対する入力が「引数」、メソッドからの出力が「返値」と整理するとわかりやすいと思います。

 この「引数」として、別のメソッドの実行結果(返値)を渡したい場合には、以下のような記述が可能です。

メソッドA( メソッドB() );

(上の例では、メソッドAにメソッドBの実行結果を渡すことになる)

 例えば「readLine」から返される<キーボードから入力された文字列>を「parseInt」の引数として渡したい場合、以下のように記述します(BufferedReaderクラスのインスタンス名をreaderとする)。

Integer.parseInt(reader.readLine() );

 先にまず「readLine」が実行されて、その結果を基に「parseInt」が実行されます。ここには書かれていませんが、もちろん「parseInt」の実行結果(返値)は代入文を用いて左辺に用意された整数型変数で受け取ります。

 ということで、やっと「ClassInfo」改造のために必要な知識がすべて紹介されました。あとはコメントを参考に、上記のプログラムを完成して下さい。

>>解答例のプログラム

(2)「ClassTableクラス」にキーボードからの入力を行うメソッドを記述する

 前回の改造で「ClassInfoクラス」は2回分の「授業の情報」をキーボードから入力できるようになりました。しかし講座3で学習したとおり、このような処理はあらかじめ「ClassTableクラス」のメソッドとして登録しておいた方がよさそうです。なぜなら「授業の情報」とは「ClassTable」クラスの属性のことであり、属性に値を与えるという処理は「ClassTableクラス」を利用する限りたびたび行われることになるだろうと予想されるからです。

 そこで今度は「授業の情報」をキーボードから入力させるためのメソッドを「ClassTableクラス」に記述してみます。

 新しいメソッドを作成する場合、そのメソッドが呼び出されたときにどのように使われるかを考えてみることで、より便利なメソッドを作ることができます。例えばこれから作成するメソッドの名前を「inputData」にするとして、それが「ClassInfoクラス」のメイン・メソッドの中でどのように呼び出されて使われるのが便利なのかを考えます。例えばこのように呼び出されるとします(ClassTableのインスタンスをinfo1とする)。

info1.inputData();

 この1行の呼び出しによって3つの属性(no,subject,room)すべてに値をキーボード入力させたい場合、「ClassTableクラス」の方には以下のように3つの値のキーボード入力に必要なすべての命令を記述することになります。

public void inputData() throws Exception{
	try{
		/*「BufferedReader」をインスタンス化する*/
		BufferedReader reader = new BufferedReader(newInputStreamReader(System.in));

		/*readLine()メソッドを利用して「授業の情報」の内容をキーボードから読み込む*/
		no = Integer.parseInt(reader.readLine());	// 「時限」を読み込む
		subject = reader.readLine();			// 「科目名」を読み込む
		room = reader.readLine();			// 「教室名」を読み込む

	}//エラーが発生したらエラーメッセージを示しプログラムを終了する
	catch(Exception e){System.out.println("エラーが発生したのでプログラムを終了します");}
}

 赤字で記したメソッド名のあとの「throws Exception」は、処理手順の中に「例外発生」の可能性を含むメソッド(この場合はreadLine())を利用した場合に必ず書かなければなりません。このメソッドの呼び出し元に対して、処理を実行中にもし「例外」が発生した場合にそれを知らせるための記述だからです。またこの場合、このメソッドの呼び出しもとは必ず「try{ }catch(Exception e){}」の中でこのメソッドを呼び出さなければなりません。

 さて、「inputData()」をどのように作るのかの一例を示しましたが、ここでは後々のことを考えてもう少し違う設計をしてみたいと思います。いま示した例ではメソッドの処理手順の中で「BufferedReaderクラス」のインスタンスを作るようにしました。しかし、さきほど「その1」の中でも触れたことなのですが、「BufferedReader」はインスタンス化される際の()内の記述次第で、入力先をキーボードからではなくテキストファイルからにすることもできるのです。そこで、「BufferedReader」のインスタンス化はメソッドの呼び出し側(この場合にはClassInfoのメイン・メソッド)に任せることにして、「BufferedReader」のインスタンスを引数として受け取れるように「inputData()」を設計しましょう。なぜならそうすれば、このメソッドは「キーボード」「テキストファイル」のどちらからの入力にも対応できるからです。

 自分でメソッドを作成する際に、引数を受け取れるようにするためには、メソッド名の直後にある()内に受け取りたいデータの型と同じ型の変数を準備しておきます。呼び出し元から与えられる引数を受け取るための受け皿が必要だからです。もしも受け取りたいのがあるクラスのインスタンスなら、クラス名と受け皿として仮に用意するインスタンス名を書いておきます。例えばこのようにしておけば、

public void inputData( BufferedReader reader)throws Exception{

このメソッドが「ClassInfo」のメインメソッドで呼び出された際に、「BufferedReader」クラスのインスタンスを引数として受け取ることができるのです。

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

info1.inputData( x);

 上の例は「ClassInfo」のメインメソッドで実際に「inputData()」が呼び出される際の書式例です。「x」という名前の「BufferedReader」のインスタンスが「inputData()」に引数として渡されています。すると、この渡されたインスタンスは、「inputData()」の定義に記述されている受け皿の「(BufferedReader reader)」の部分で受け取られるのです。「inputData()」の処理手順を実行してゆく間、今度はこの「BufferedReader」のインスタンスは「reader」という名前で呼ばれ利用されます。

 この実際に渡される引数「x」のことをプログラミングの世界では一般に「実引数」と呼びます。それに対して、メソッドを定義する際あらかじめ用意しておく引数の受け皿のことを「仮引数」と呼びます。

 それではコメントを参考にしながら以下の「ClassTable.java」を完成させて下さい。設計通りに「inputData()」が作成されたものとして、それを利用するように書き換えた「ClassInfo.java」も用意しましたので、参考にして下さい。

>>「inputData()」を利用した「ClassInfo.java」

/* 「授業表」の定義 */

//入出力関連パッケージの利用を宣言する

public class ClassTable{

	int no;		// 属性1・時限
	String subject;	// 属性2・科目名
	String room;	// 属性3・教室名

	/* メソッド1・属性の値を表示する */
	public void showData (){

		System.out.print("時限:");
		System.out.println(no);		// 「時限」の値を表示して改行
		System.out.print("科目名:");
		System.out.println(subject);	// 「科目名」の値を表示して改行
		System.out.print("教室名:");
		System.out.println(room);	// 「教室名」の値を表示して改行
	}

	/* メソッド2・属性の値を入力する */
	public void inputData( BufferedReader reader )throws Exception{
		try{

			System.out.print("時限:");	//ユーザーに入力の対象を示す
			//「時限」の値を入力する
			System.out.print("科目名:");
			//「科目名」の値を入力する
			System.out.print("教室名:");
			//「教室名」の値を入力する

		}//エラーが発生したらエラーメッセージを示しプログラムを終了する
		catch(Exception e){System.out.println("エラーが発生したのでプログラムを終了します");}
	}
}

>>解答例のプログラム


リンク:

<全体のトップページ>

     |

<第4講のトップページ>

     |-------------------------|

<第4講・その1>       <第4講・その2>