はじめに (BasicのようにJavaを学ぼう)
プログラミングの教育に使われる言語は、Basic, C, Javaと推移してきました。これらの言語は車に例えると、それぞれ、オートバイ、乗用車、大型車、といった感じです。一方、学生さんのプログラミング能力を見ていると、最近落ちてきた印象を受けます。何より心配なのは、プログラムを楽しんでいる人が少ない感じがすることです。この原因の一つにJavaの特性が関係しているのではないかと思いだしています。Javaは高度なプログラムを実現するため、様々な機能が取り込まれています。そのためJavaを頭からトップダウンに学習していくと全貌を理解するまでに疲れきって脱落してしまうのではないかということです。
そこで、新しいアプローチとして考えたのは、学生さんにJavaの細かなこと(かなり多いのですが)は“おまじない”として目をつぶってもらい、必要最小限のBasicレベルからボトムアップに学習し、何よりプログラミングの楽しさを先に経験してもらおう、というものです。本テキストは、その方針でまとめました。
次の図は、プログラミング言語Javaを、命令とデータ構造の切り口で分解し、テキストの章との対応を示しました。皆さんがJavaの全貌をトップダウンに見られるのは、秋学期後半になることでしょう。それでも、トップダウンに進まないと納得できない方もいるかと思います。そういう方は、参考書を読まれるとよいと思います。参考書のほとんどはトップダウンに説明を行っています。
それでは、プログラミングを楽しまれますよう、お祈りして。出発!!
第1章 流れ図と変数 (流れ図(flow chart)で変数のイメージをつかむ)
最近あまり使われなくなりましたが、以前はプログラムを書く際、必ず作成しました。ここでは、流れ図を紹介しながら、“変数”と“繰り返し”のイメージを学んでもらいます。
1−1 流れ図
正確なプログラムを作るために、計算機の手順を図式化したものが流れ図です。流れ図はプログラム以外でも用いられているので親しみやすく、プログラムを直感的に理解することができます。
本章では、簡単な例を使いながら流れ図を説明します。流れ図では数値を格納する“変数”というものを使います、変数はプログラムで重要な役割を果たすので、ここでイメージを掴んでおきましょう。
<例1>キーボードから2数を入力し、小さい方の数値をディスプレーに表示する流れ図を示します。キーボードから入力される2つの数は、計算機のaという記憶場所(変数)と、bという記憶場所(変数)に格納して処理するものとしましす。
変数の特徴: 変数はデータを記憶する場所。黒板のような感じで、一度データを格納する(書き込む)と、次にデータを格納する(書き込む)まで、先に格納したデータは消えない(新しいデータの格納で古いデータが消える)。格納したデータは何度でも読み出せる(読み出しによってデータは消えない)。
流れ図で用いられる主な記号は以下の通りです。
<例2> 直線的な流れ図
数値をnという場所(変数)に入力し、n3 を計算して結果をmという場所(変数)に格納し、その後mに格納されている数値をディスプレーに表示します
<例3> 繰り返し(ループ)を持つ流れ図
同じ作業を繰り返し行うのは計算機の得意とする所です。極端に言えば“プログラムは、目的とする仕事を‘繰り返し処理’に変換する作業”と言えます。
次の図は“1~10までの自然数の和を求める”流れ図です。
最初sという場所(変数)に0を格納しておき、sに順次1,2,3,…,10を加える処理を流れ図にしています。
sß 0; (sという場所(変数)に0を格納)
sß s + 1;(sという場所の数値(現在0)に1を加えてsに書き込む(sの数値は1になる))
sß s + 2; (sという場所の数値(現在1)に2を加えてsに書き込む(sの数値は3になる))
:
sß s + 10;
とするところを、次のようにiという変数を使って繰り返し計算に持ち込んでいます。
s ß s + i; { s + i(sに格納された数とiに格納された数を加え)の加算結果をsに格納}
i ß i+ 1; {iという場所に格納されている数値に1を加え、結果をiという場所に格納}
流れ図には、色々な流派があり、繰り返し部を6角形マークで挟む方法もあります。次の流れ図は上と同じ問題を、6角形で挟む方式で描いたものです。
この方式は、後述プログラムのfor文を意識したもので、プログラムに変換しやすい形といえます。図の右には変数i, s の遷移を示します。
第2章 最初のプログラム
本章では、プログラムとプログラムを構成する“計算機の命令”を説明します。すごい処理を行う計算機ですが、計算機の実行できる命令はほんの少しです。この少しの命令を使って複雑な処理を実現します。ほんの少しの命令ですので、よく理解しておきましょう。
2−1 プログラムと命令 (命令は、プログラムで“文”と呼ばれる)
プログラムは、いくつかの行からできています。各行は文と呼ばれる(計算機への)命令です。これらの命令は、処理の流れを変える命令がない限り、上の命令から下の命令へと順に実行されます。
計算機の命令(文)は、次の5種類です。
入力文 |
キーボードからの入力 |
変数名 = tohoin():東邦古谷だけの命令 |
出力文 |
画面への表示 |
System.out.println(変数名); |
代入文 |
変数へ数値や計算結果を格納 |
変数名=数値; 変数名=計算式; |
条件文 |
条件による分岐 |
if(条件){条件を満す時の処理} else{条件を満さない時の処理} |
繰返し文 |
同じ処理の繰り返し |
for(変数初期設定;繰返し条件;変数値変更){ 繰り返し処理} |
以下に、これらの命令の意味、書き方、使い方を紹介します。
2−3 代入命令(代入文) (本章で扱う数値は全て整数とする)
代入とは、変数へ数値を格納(書き込む)することです。
代入には“=”マークを使いますが、これは”等しい”という意味ではなく”ß”の意味であることに注意して下さい。
変数へ数値を代入する形式(フォーマット)は、次の4つです。
(i) 数値を直接代入する: 変数名=数値; (例 a=5;)
(ii) 変数の中身を、変数に格納: 変数名=変数名; (例 a= b;)
(iii) 数値や変数を使った計算結果を、変数に格納: 変数名=計算式;(例 a= a+5;)
(注意!代入命令では、=の左辺の変数の値は変わるが、右辺の変数の値は変わらない)
2−4 入力命令(入力文)
キーボードから数値(整数)を入力(読み込む)する命令です。
当面 TohoIn(); という命令を使います (Javaでの入力命令は煩雑なので、本テキストの著者が、簡単な命令TohoIn()を作りました)。
キーボードから整数を読み込み、変数に数値を代入するには次のようにします。
変数名=TohoIn(); (例 i=TohoIn();)
(補足)TohoIn()は、数値をキー入力しEnterキーを押すと数値の入力が完了します。また、入力された数値は画面に表示されます。
2−5 出力命令(出力文)
(i) 数値を出力する場合: System.out.print(変数名);(例 System.out.print(a);)
(ii) 文字列を出力する場合:System.out.print(“文字列”);
(例 System.out.print(“hello”);)
(補足)出力後改行する時はSystem.out.printの代わりにSystem.out.printlnを用います。
<代入文、入力文、出力文を使ったプログラム例>
プログラム例1
これまでの命令を使ったサンプルプログラムを示します。
プログラム1 a= 5; b= 3; c= a*b; System.out.println(c);
プログラム1:変数aに5を代入し、変数bに3を
代入し、aとbを乗算し結果を変数cに代入し、
結果を出力。
プログラム2:キーボードから数値をaという変数に代入し、aに1を加えて、結果を出力。
プログラム2 a= TohoIn(); a= a+1; System.out.println(a); プログラム2 a= TohoIn(); System.out.println(a+1);
プログラム3:変数iに1を3回加える(変数iには最初(初期値)0を入れておく)
プログラム3 i= 0; i= i+1; i= i+1; i= i+1; System.out.println(i); プログラム3 i= 0; i= i++; i= i++; i= i++; System.out.println(i);
出力結果は3になります。
2−7 条件文(if 文)
ある条件を、満たすか満たさないかを判断し、それに応じて処理の内容をかえる場合には、if文を使います。If文には次の2つのフォーマットがあります。
if(条件){条件を満たすときの処理} if(条件){条件を満たすときの処理}else {条件を満たさないときの処理}
if文の(条件)は、大きい、小さい、等しい、などの大小関係で次の記号を用います。
大小関係 |
java |
a=b |
a==b |
a≠b |
a!=b |
a<b |
a<b |
a≦b |
a<=b |
プログラム4 a= TohoIn(); if( a==0){ System.out.println(“error”); }
<if文を使ったプログラム例>
プログラム4:変数aにキーボード
から数値を入力し、0が入力された時
だけerrorと出力せよ(0以外の時は
何もしない)、
プログラム5 a= TohoIn(); b= TohoIn(); if (a<b){System.out.println(b);} else {System.out.println(a);}
プログラム5:変数aと変数bに数値
をキーボードから入力し、大きい方の
変数の数値を出力する。
プログラム6:変数aに数値を
プログラム6 a= TohoIn(); b= a%2; if(b==0){System.out.println(“even”);} else{ System.out.println(“odd”);}
入力し、それが偶数なら”even”、
奇数なら”odd”と出力する。
プログラム7 a= TohoIn(); b= TohoIn(); if(a<b){c= b-a;} else{ c= a-b;} System.out.println(c);
プログラム7:変数a,bに数値を
入力し、大きい方の値から小さい
方の値を引いた数値を出力する。
(右のプログラムではa=bの時は
elseの方で処理されている)
(注)if文で、{ }の中が1行の場合は、カッコ ”{“ “}”を省略できますが、初心者の場合は、省略しないこと。
2−8 繰り返し命令(for文)
同じ処理を定められた回数だけ繰り返すには、for文を用います。for文では、繰り返し回数を制御する変数(以下、繰返し制御変数と呼ぶ。i, j, kを用るようにしよう)を用います。
for文は次の形式(フォーマット)で書きます。
for(繰返し制御変数の初期設定;繰返し条件;繰返し制御変数の変更){ 繰返し実行するプログラム }
for文が実行されると先ず、“繰返し制御変数の初期設定”が実行され、次に“繰返し条件”がチェックされ、条件が満たされていれば“繰返し実行するプログラム”が実行される。その後、“繰返し変数の変更”が行われ、再び“繰返し条件チェック”に戻ります。
(注)for文で、繰り返し実行するプログラムが1行の場合には、カッコ”{” “}”を省略できますが、初心者の場合は、省略しないこと。
下図は上に書いたfor文の実行過程を流れ図にしたものです。右図はfor文の例です。
次のプログラムは、forが2重になった例で、2重ループのプログラムと呼ばれます。この場合の、繰返し制御変数 i, jと、変数a の変化を次に示します。
int i, a=0; for( i=0;i<2;i++){
for( j=0;
j<3;j++){ a= a+i+j; } }
右のプログラム最初のループは
i=0 j=0なので、aはa<=0+0+0で、aは0、次は
i=0, j=1なのでaはa<=0+0+1で、aは1、次は
i=0, j=2でなのでaは a<=1+0+2で、aは3、次は
i=1 j=0でaはa<=3+1+0でaは4、次は
i=1, j=1でaはa<=4+1+1でaは6、次は
i=1, j=2でaは a<=6+1+2でaは9、となる。
<for文を使ったプログラム例>
プログラム7 for( i=0; i<100; i++){ System.out.println(“hello”); }
プログラム7:helloと100回出力する。
プログラム8 for( i=0; i<100; i++){ System.out.println(i); }
プログラム8:0から99まで出力する。
プログラム9 for( i=0; i<100; i++){ System.out.println(i+1); }
プログラム9:1から100まで出力する。
プログラム10:1〜100までの和を計算して出力する(流れ図の例3)。
プログラム10 s=0; for( i=0; i<100; i++){ s= s+(i+1); } System.out.println(s);
プログラム11:掛け算の九九を表示する。(2重ループの例)
プログラム11 for( i=0; i<9; i++){ for(j=0; j<9; j++){ m=(i+1)*(j+1); System.out.print(m); } System.out.println(); }
演習問題:
(1)円周率は整数3とする。変数hに数値(半径)を入力すると、円の面積(整数)と円周長(整数)が出力されるようにせよ。
(2)変数aとbに適当な数値を入れておく(代入文)。aの中身(数値)とbの中身(数値)を入れ替えよ。(ヒント:数値を一時退避する変数を用意する必要がある)
(3)キーボードから入力した数値を出力する処理を5回繰り返せ。
(4)1が入力されたらjan、2が入力されたらfeb、3が入力されたらmarと出力せよ。
(5)変数a, b, cに適当な数値を入れておく。これらの中の最大値と、最大値が入っている変数名を出力せよ。
(6)変数a, b, cに適当な数値を入れておく。これらの数値を、大きい順に出力せよ。
(7)画面に次のように表示せよ。2重のfor文とif文を使用せよ。
**********
* *
* *
* *
**********
(8)変数a, bに適当な数値を代入しておく。ab(aのb乗)を求めよ。
(9)変数(整数)a, b, cに適当な数値を代入しておく。a,b,cの和を3で割った値をhに代入し、結果を出力せよ。
(整数同士の割り算では、割った結果は少数点以下は切捨てられることを確認すること)
(10)変数aに数値nを入力し、n! 即ち(1*2*…*n)を求めよ。
第3章 プログラミング実習
やっとプログラムの実習と言いたい所ですが、これからハッピーにプログラム開発を行っていくために、Jcpadという開発環境を準備しましょう。
3−1 開発環境の準備
Jcpadは、以下のサイトからダウンロードし、インストールします。
http://www.vector.co.jp/soft/win95/prog/se153698.html
インストールするとjcpad…というフォルダーができます。フォルダーを開くと、次のようなものが入っています。
この中にあるjcpad.exeというフォルダーをWクリックすると、開発環境が立ち上がります。
下図がJcpadの開発環境です。図のメイン(上の)ウインドウがプログラム作成部で、下方のウインドウにはエラーメッセージが表示されます(付録C参照)。
<Javaプログラム作成から実行まで>
プログラムの作成から実行までは、次の作業が必要です。
Step1:プログラム作成(〜.javaというファイルを作る)
Step2:プログラムのコンパイル(〜.classというファイルができる)
(コンパイルとは:人間に分かるプログラム〜.javaを、計算機に分かるプログラム〜.classに変換する処理)
Step3:実行(計算機が〜.classのプログラムを実行)
<Jcpadに関する、追加説明>
Jcpadをインストール時には、javacの在りかと、開発プログラムを格納する場所を聞いてきます。
予め、javacの場所を調べ、プログラム格納フォルダーを決めておきましょう(上図の”必須”部)。上記の例は本テキストの著者の場合です。計算機により違いますので、そのまま書いても駄目です。
なおこの、設定は、後からJcpad開発環境の“実行”タグの“設定”で設定することもできます。
(注:javacの探し方:家のPCの場合、Javaをインストールすると、Cドライブの下にj2sdk1.4.2.???というフォルダーができます。この中のbinというフォルダーの中にあると思います。イクスプローラでファイル名を指定して検索をかけても出てくると思います。
大学の場合:(計算機室により異なる場合があるので)担当教員かTAに聞くのがよいと思います。)
3−2 整数型int, 実数型double, キャスト(…)
前章までの説明で扱う数値は整数と決めてきましたので、無視してきたことがあります。それは変数の宣言です。Javaでは整数の他に実数(例えば2.3のように小数点の付く数値)も扱えます。変数は数値を格納する場所ですが、どんな数値でも格納できるわけではありません。整数は整数用の変数に、実数は実数用の変数に格納するよう決められています。例えて言えば、フルートはフルート用のケースにしまい、トランペットはトランペット用のケースにしまわないとうまく入らないって感じです。プログラムでは整数や実数を“データの型(タイプ)”と呼び、それを格納する変数の方も“整数型の変数”とか“実数型の変数”というように、きちんと区別して使います。
そのため、プログラムでは最初に、変数名とその型を宣言しておく部分が必要になります。整数型はint, 実数型はdoubleと変数名の前に書いて宣言します。変数宣言時に、変数に初期値をセットするには、変数名に数値を代入する形にします(例:int a=5;)。
演算も、整数型は整数型同士、実数型は実数型同士で行わなければなりません。例えば上のプログラム例で、c= d / b; というような書き方はできません。データ型が違うもの同士の演算をしたい場合、左辺のデータ型に合わせて右辺の変数を一時的に型変換します。これを“データ型のキャスト”と呼び、()内に変換先の型名を書きます。c= d / b; の場合、cは実数型なのでcの実数型に合わせ、bを実数型にキャストし、c= d / (double)b; とします。キャストは変数ごとにやりましょう(c= (double)(d / b)ではいけません)。
数値は小数点を付けると自動的に実数と認識されます(3は整数で、3.0は実数)。
3−3 型紙を使ったプログラミング演習
“はじめに”の部分で述べたようにJavaは自動車で言うと大型自動車です。オートバイに相当するBasicと呼ばれる言語ですと、前章のプログラムで(データ型も定義せず)、すでに実行することができます。Javaは高機能なため、今までのプログラムに色々(おまじないの様)な飾りを付けないと実行できません。
“おまじない”の説明から入る方法もありますが、煩雑なので、しばらくの間(秋学期末まで)“おまじない”には目をつぶり、プログラム核心部の作成練習に集中して進みます。具体的には、プログラム用の2つの型紙に、皆さんの作ったプログラムを書き込んでいき、実行します。“おまじない”を含んだ全体(型紙)がJavaのプログラムです。
Javaプログラムは大きく分けると、アプリケーションというものとアプレットというものに分かれます。実習に使う2つの型紙は、この2つ(1)アプリケーションと、(2)アプレットに対応しています。2つの違いは次の通りです。
(1) アプリケーション:main(…){…}という構造があり、本格的プログラムを作る時使います。
(2) アプレット:ホームページに貼り付ける簡単なプログラムを作るのに使われます。自動的にウインドウを開いてくれるので、描画等に便利です。本章では、簡単にアニメーションを行う型紙を使用します(画像が動いた方が楽しいので)。
この2つの型紙では、型紙への皆さんのプログラムの記入法が異なります。上の図は、その様子を示しています。具体的には、次節で説明します。
3−4 アプリケーションプログラムの作成
次の図は、アプリケーションプログラム作成用型紙です(章末の付録からコピー可)。
皆さんが変更する部分は、
(i)
プログラム名と、 (ii) プログラム本体、
の2箇所です。プログラム名は、大文字ではじまり、途中に Kadai-1というように− は入れないこと。−を使いたい時は、_ を使うこと。
このプログラムは、数字を入力しては表示、という処理を3回繰り返します。TohoIn()は元々、入力時に数値を表示しますので、このプログラムでは同じ数字が2回続けて表示されます。
プログラムの実行法(Jcpadの場合)
step1: Jcpadの上部のウインドウにプログラムを作成し
step2: ファイルに保存(ファイル名はプログラム名.java)
step3:
Jcpad上部のコマンドツールボックスの右向き三角(青色)をクリック
プログラムの実行法(コマンドプロンプトの場合)
step1: テキストエディターでプログラムを作成し
step2: ファイルに保存(ファイル名はプログラム名.java)
step3: DOS窓(コマンドプロンプト)で<javac
プログラム名.java>と入力しコンパイル
step4: DOS窓(コマンドプロンプト)で<java プログラム名>と入力し実行
3−5 アニメーション(アプレット)の作成
次の図は、アニメーションプログラム作成用型紙です(章末の付録Dからコピー可)。
アニメーションプログラムは、アプリケーションと違い、型紙の3箇所を変更します。
(i) プログラム名(2箇所)
(ii) 変数宣言部
(iii) プログラム本体
アニメーションは、描画関連処理、お休み、描画関連処理、お休み、を繰り返すことで絵が動いて見えます。下図の(iii)プログラム本体部とある部分が1回の描画関連処理で、その後のThread.sleep(100);が100msのお休みです。
描画関連処理部では描画のための描画命令を出しますが、ここでは描画命令を直接書くのではなく、repaint(); と書いておきます。そしてrepaint();で実行される実際の描画命令は、paint(Graphics g){…}の括弧内に書きます。描画命令は付録にまとめておきます。
上のプログラムを実行すると、描画ごとに描いた図は消えますが、図を消さずに描画を続けるには、//でコメントアウトした行の先頭の//を消します。
(注:文の先頭に//と書くと、その行は実行されないため、コメントを書くことに使える)
このプログラムでは円が左から右に移動します。変数xが円のx座標です。
プログラムの実行法(Jcpadの場合)
step1: Jcpadの上部のウインドウにプログラムを作成し
step2: ファイルに保存(ファイル名はプログラム名.java)
step3:
Jcpad上部のコマンドツールボックスの右向き三角(青色)の左のマークをクリック
step4:
Jcpadの上部のコマンドフィールドに(appletviewer
プログラム名.java)と書き、コマンドフィールド右の実行マーク(青三角)をクリック
プログラムの実行法(コマンドプロンプトの場合)
step1: テキストエディターでプログラムを作成し
step2: ファイルに保存(ファイル名はプログラム名.java)
step3: DOS窓(コマンドプロンプト)で<javac
プログラム名.java>と入力しコンパイル
step4: DOS窓(コマンドプロンプト)で<appletviewer プログラム名.java>と入力し実行
演習問題:
(アプリケーション)
(1) 半径(整数)を入力し、面積(実数)を計算し出力せよ。
(2) 数を2つ入力し、2数の平均値(実数)を出力せよ。
(3) 複数のデータ(整数)を入力し、その合計を平均を求めよ。最初に、読み込むデータの数を入力すること。(ヒント:最初に繰り返し数を変数 n に入力し、for文の繰り返し条件をi<n とする。)
(アニメーション)
(4) 3本の平行線を描け
(5) 3本の平行線に3本の垂直線を(格子状に)描け
(6) ボールを大きく左右に往復運動させよ。(ヒント: for(;;){繰返し部} は“繰返し部”の無限繰り返しを意味する。ボールの座標を変数xで表し、変数dをボールの方向(+1が右、-1が左)に使う。x=x+d;でボールの位置を変える。xが右端に来たらdを−1にし、xが左端に来たらdを1にする。)
(7) ボールの座標をx、yで表し、(6)を2次元的に拡張して、ボールをビリヤードのように上下左右の壁で反射させて動かせ。
付録A : 描画命令
(注意:描画命令は型紙1(アプリケーション)では使えませんので注意して下さい)
画面に描画する位置は、ウインドウ左上隅を原点(0,0)とし、右方向をx方向正、下方をy方向正とする、ピクセル位置で指定します。
1.円や楕円を描くには:g.drawOval(x,y,w,h)
(x, y, w, hの意味は、右図参照)
2.直線は:g.drawLine(x1,y1,x2,y2)
ここでx1,y1は始点の座標、x2,y2は終点の座標
3.四角は:g.drawRect(x,y,w,h);
(x, y, w, hの意味は、右図参照)
描画図形の色は、ペンの色によって決まる、と考える。ある色のペンを1度持つ(g.setColor)と、ペンを持ち替えるg.setColorまでペンの色は変わらない。
4.色指定:g.setColor(色名)
ここで(色名)は、Color.red,Color.magenta,Color.blue,Color.cyan,Color.pinkなんて指定。
5.3原色による色指定:g.setColor(new Color(赤成分,緑成分,青成分));
ここで、赤成分、緑成分、青成分は0〜255の整数。
6.塗りつぶした図形はg.fillOval(…), g.fillRect(…)等で描かれる。
7.文字列の表示命令は、g.drawString(文字列, x座標, y座標)
付録B: プログラムのルール集
プログラムの構造がすっきりしていないと、誤りが起こりやすくなり、デバッグ(エラー修正)が難しくなります。美しいプログラムを書くよう心がけましょう。当面、気をつけるべきルールを以下の図に示します。
付録C エラーメッセージの読み方
コンパイル時エラー
Javaのエラーメッセージは(特に初心者には)親切とは思えません。次のサイトに、エラーメッセージの一覧が示されています(http://javafaq.jp/#S172)。
全部読むのも大変なので、よく出くわすものを挙げておきます。
step1:エラーの有った行番号が表示されるので、先ず、そこをチェックしよう。
step2:エラーの箇所は^で指定されるので参考にしよう。
(1)error: cannot read: Sample.java
指定したファイル(この場合はSample.java)が見つからない、というエラーです。作ったファイル(Sample.java)がある場所を確認して下さい。
(2)class Sample is public, should be declared in a file named Sample.java
public class Sample {
プログラム名とファイル名が違っていないか?
(3)シンボルを解決できません
主に、以下の場合です。
スペルミス
型宣言の書き忘れ
引数の個数が違う
引数の型が違う
エラーメッセージの後に(BufferdReaderなどの)入出力関係のクラスが指示されている場合 io.java.* という入出力関係のパッケージを読み込んでいるかどうかチェックしましょう。
(4)<identifier> がありません
書いてはいけない場所に、文や綴りを書いた場合です。
(5) ‘;’がありません
文末の;を確認しましょう。
(6) ‘}’がありません
}を確認しましょう
(6)’class’または’interface’がありません。
(7)unclosed string literal
System.out.println("")によって出力する文字列が途中で改行されていないかチェックしてください。改行が含まれている文字列はひとまとまりのものとして操作されないために、エラーを起こします。Javaでは、出力の改行を行なうために、System.out.print( )とは別にSystem.out.println( )という関数を用意しているのです。
(8)12288は不正な文字です
全角スペースが入っています。
実行時エラー
(1) java.lang.NoClassDefFoundError
主に次の場合です
コンパイルエラーでコンパイルが完了していない
コンパイル済みのclassファイルが希望の場所にない
java Sample.javaとか、 .javaなどを付けてしまった場合
(2) java.lang.ArrayIndexOutOfBoundsException: 6
at Sample.main(Sample.java:5)
配列のサイズを超えた場所にアクセスしようとしています。
(3) java.lang.NullPointerException
宣言していないものにアクセスしようとした時などにでます。
付録D: プログラム開発用型紙
(1) アプリケーション
import java.io.*;
public class Mn {
static int TohoIn() throws IOException{
BufferedReader br= new BufferedReader(
new InputStreamReader(System.in));
return Integer.parseInt(br.readLine());
}
public static void main(String args[]) throws IOException{
/////////Your Program Start……………
int data, i;
for( i=0; i<3; i++){
data= TohoIn();
System.out.println(data);
}
/////////Your Program End……………..
}
}
(2) アニメーション
/*<applet code="Ball.class" width=300 height=300></applet>*/
import java.applet.*;
import java.awt.*;
public class Ball extends Applet implements Runnable{
////////Your Variable Start......
int x= 20;
////////Your Variable End.........
Thread th;
public void start(){
th= new Thread(this);
th.start();
}
public void run(){
try{
for(int i=0; i<100; i++) {
/////////Yor Program Start.......
repaint();
x= x + 5;
/////////Your Program End........
Thread.sleep(100);
}
}catch(InterruptedException e) {}
}
public void paint(Graphics g) {
/////////Your Draw Start.........
g.drawOval(x,90,20,20);
/////////Your Draw End...........
}
// public void update(Graphics g){paint(g);}
}
第4章 配列
配列(array)は、変数を並べて一くくりにして名前を付けたもので、繰り返し計算に便利なデータ構造です。
4−1 配列の分類
先ず、配列の構造による分類を覚えておきましょう。Excelで横1行しかない場合、これが1次元配列です。Excelの1枚シート、これが2次元配列です。シートが複数重なったもの、これが3次元配列です。配列には名前を付け、配列内の要素(1つのマス)はインデックス(Javaでは添え字と呼ばれるが、機能的には場所を指すポインタと呼んだ方がよい)で指し示されます。
(1) 1次元配列
右図は配列名hairetu(配列名も変数名と同じで自分の覚えやすい名前を付ける)、配列要素(数値の入るマス)数3の1次元配列です。
この配列を宣言して、ついでに右のように初期値を
入れる(代入するという)には次のようにする。
int hairetu[]={6,4,7};
(2) 2次元配列
下図はEXCELの表の一部です、2次元配列は、この表のイメージです。これは3×4の2次元配列です。EXCELではセル(マス)を(3.A)なんて指定します(3.Aは9)。しかしJavaでは下図の縦1,2,3,を0,1,2と指定し、横A,B,C,Dも0,1,2,3と指定します。ですから、もし、下の2次元配列名をhairetu2とすると、hairetu2[2][0]の値が9になります。要素位置指定は“縦”“横”の順ですので注意してください。この2次元配列を宣言し下のように初期値をセットするには次のようにします。
int hairetu2[ ][ ]={{5,8,7,6},{4,1,2,12},{9,3,10,11}};
hairetu2[1][3]
(3) 3次元配列
下図はEXECLの表です。図の下の方にSheet1,Sheet2,Sheet3とシートが重なっているので、今度はシート番号も指定できます。これが3次元配列です。セル(Sheet1.3.A)の数値は9です。JavaではSheat1を0、Sheat2を1、Sheat2を3と指定しますので、Sheat1の3.Bは、hairetu3[0][2][1]となります。位置指定が“奥行き(Sheat)”、“縦”、“横”、の順ですので間違いなきよう。
hairetu3[0][2][3]
4−2 配列の操作
配列は繰り返し計算と大変相性がよく、ほとんどのプログラムの中核になっています。配列と繰り返しの合体の基本は、“配列(下図ではh1)の要素を指すポインタ”を変数(下図ではi)にすると共に、この変数をfor文の繰り返し制御変数にすることにより実現されます。次の例は、その代表で、配列の全要素に0を代入する方法です。
配列操作の基本形は、いくつもありません。ほとんどのプログラムは、この基本形の組み合わせで作成できます。
配列操作の基本形を並べますので、マスターしておきましょう。
(1) 配列要素に数値を代入する
2×3の、2次元配列h2の要素に i の数値を代入するの場合(右図は実行結果)
for(i=0; i<2; i++){ for(j=0; j<3; j++){ h2[i][j]= i; } }
(2) 列要素すべてを出力するするには
(3) 配列要素の総和を求める
(4) 配列要素の最大値(最小値)を求める
(最大値を求める時の常套手段):“仮の最大値”を入れる変数を用意し、最初小さな値を入れておく。“仮の最大値”と配列要素と比較し、仮の最大値より大きな要素があれば、“仮の最大値”に配列要素を書き込む。
(5) 配列要素を(横方向、または縦方向に)シフトする
左シフト(右端は、元のままの数値が残る)
右シフト(左シフトのようにiを変えられないのは何故か考えてみよう)
(6) 配列要素同士の演算
h2の各列において、第0行目と第1行目の積を第1行目に代入する
for(i=0; i<3; i++){ h2[1][i]= h2[0][i] * h2[1][i]; }
(7) 配列の入れ替え(スワップ)
h2の第0行目と第1行目を入れ替える。
for(i=0; i<3; i++){ buf=h2[0][i]; h2[0][i]= h2[1][i]; h2[0][i]= buff; }
a
演習問題:
(アプリケーション)
(1) 配列aの最大値と、最大値が入っている要素番号
(行番号、列番号)を出力せよ。
b
(2)配列bの中身を、左右逆にして配列eに入れよ。
(for文を使うこと)
(3)配列cとdの対応する要素を掛け、結果をeに書け。
(4)配列cとdの対応する要素を比較し、大きい方の
数値を、対応するeの要素に代入せよ。
(5)配列bの中身を右シフトし、右端からはみ出した
数値は左端に代入せよ。
(6)キーボードから数値を1つ入力する。配列aの中で、入力された値と同じ値を持つ要素番号(x、y)を出力せよ。
(アニメーション)
(7)配列fの各行を、点のx、y座標と考え、5点を
中心とする5つの円(直径20)を描け。
(8)配列fの各行を、点のx、y座標と考え、上から
5点(5行)を一筆書きで描け。
(9)最初座標(100,100)に円を描く。キーボード
から数値を入力し、その数値分だけ円を左右に移動させよ。
入力された値が正なら右、負なら左とする。移動をfor文で繰り返し行えるようにせよ。
第5章 関数(Javaではメソッドと呼ばれるが、ここではあえて一般名詞で関数と呼ぶ)
関数の基本形は次の図で、関数にデータを入力すると、計算結果が戻ってきます。
関数は大きく分けると2種類(Javaに用意されているものと自作のもの)あり、これらを順に説明していきます。
5−1 組み込み関数
始めからJavaに用意されている関数で、代表的なものは、数学用ライブラリ関数です。
例えば、
Math.sin( r )はrに角度(ラジアン)を与えるとsinの値が返ってきます。これを使ったプログラム例は、次のようになります。
double d; d= Math.sin(3.14); double d, r=0.2; d= Math.sin(r);
数学関数にはMath.sin(r)の他に、Math.cos(r), Math.tan(r), 絶対値を返してくるMath.abs(i), 0〜1の間の乱数を返してくるMath.random()など多数あります。
関数に仕事を頼む(上の例ではd=Math.sin(3.14);やd= Math.sin(r);)ことを“関数を呼ぶ”と言います。また関数を呼ぶときは、関数名の後に( )が付きます。この( )内には、関数に送る数値あるいは変数名を入れます。 ( )内のデータ(数値または変数名)は“関数の引数”と呼ばれます。Math.sinでは( )の中に角度を入れますが、関数にデータを送る必要がないものは( )の中に何も書きません(Math.random()は単に乱数を返してくるだけなので引数は、ありません)。
関数は計算結果を返してきますが、これは“戻り値”と呼ばれます。上のプログラム例では、戻り値を変数dに格納しています。引数と戻り値は数値の型(intとかdobleとか)が関数ごとに決められており、それに従って関数を利用します。
5−2 自作の関数
前節で推測が付いたかと思いますが、関数は、プログラムの中で“よく使う処理”を主処理(メインルーチン)から切り離して一くくりにしたものです(他の言語ではメインルーチンに対して、関数をサブルーチンと呼ぶこともあります)。メインルーチンで関数の機能を利用する場合、メインルーチンでは関数名を1行書くだけで済むので、プログラムがすっきり、分かりやすくなります。
当然、自作の関数を使いたい、という要望が出てきます。実は、既に皆さんは自作の関数を使っています。私(古谷)が作ったTohoInです。これを参考に自作の関数の作り方と処理の流れを見てみましょう。
下図が、自作関数を作る場合のフォーマット(基本形)です。main(){…}の前にある
kansu(){…}という部分が自作の関数で、それをmain(){…}の中からkansu()と呼んでいます。関数宣言のstatic int の後ろのkansuが関数名で、自分の好きな名前を付けることができます。
(前章の繰り返しになりますが)
関数は、プログラム中でよく使う部分を予めmainの外に作っておいて、mainの中ではそれを略した名前で使用する、ってことです。
(プログラムの流れを見ておきましょう)
計算機はmainの最初(1行目)から命令を実行していき、処理が関数kansu()に到達すると、kansu()の方に飛びkansu()の本体({…}部)を実行し、kansuの最後の命令に到達するとmainに戻りkansu()の次の命令からmainの実行を再開する。
(戻り値)
関数を呼ぶと、処理がメインルーチンから関数に移り、関数の最後に計算結果をメインルーチンに返してきます。この“関数から返ってくる値”を“戻り値”といいます。関数の計算結果(戻り値)をmain()に返す命令がreturn文です。return文の後ろの変数の値がメインルーチンに戻されます。(上の図では言うと変数rに格納されている数値が“戻り値”でメインに戻され(関数名に乗って戻ってくる感じ)、この戻ってきた値がmain()の中でdという変数に代入されています)
(蛇足ですが)returnは関数内のどこかに戻るのではなく、“戻り値”を、関数を呼んだ所に送り返す意味でのreturnですので注意して下さい。また、関数は1つの戻り値しか戻せませんので注意してください。当然、 return 0; のように数値を返すこともできます。
(関数の型)
関数宣言の最初staticの後ろに関数の型を書きます(上の図ではint)。これは、返す値(戻り値)の型を表すものです。
(補足)関数によっては“戻り値”を返す必要がない場合もあります。この場合は、return文が必要ありません。戻り値がない場合は関数の型はvoid と記述します。
(引数)
関数へデータを送ることができます。送るデータは“引数”と呼ばれ関数名の後ろの()の中に書きます。上の図でいうと、メインルーチンのnという変数の値がkansuに送られます。図では変数を使っていますが、kansu(5);というように数値を直接送ることもできます。
関数の側では引数の型を指定しています。図で言うと(int m)のintです。整数を送ってください、と言っています。メインから送られてきた数値は関数では関数内の変数に移し変えられて処理されます。上の図では、送られてきた数値は関数内の変数mに移され処理されます。そのため、データを送ったメイン側の変数の中身は一切変化しません。
メイン側の引数を“実引数”、関数側の引数を“仮引数”と呼びます(図ではnが実引数、mが仮引数となります)。
(補足)関数にデータを送る必要がない関数もあります。この時は引数を書く必要がないので関数名の後ろの()内は何も書きません。
5−3 自作関数の例
関数の具体例を2つ紹介します。
(1) TohoIn(プログラム型紙Mnを見て下さい):
キーボードから数値を入力する場合Javaでは数行の長い命令を書かなくてはなりません。これをいちいちプログラム中に書いていくと、プログラムがごちゃごちゃして見にくくなります。そこで私がキー入力をTohoInという関数にしてメインルーチンから追い出しました。
自作の関数を定義して使うには、関数の宣言と、プログラムからの呼び出しが必要です。
プログラム型紙中のstatic int TohoIn(){…..}の部分が自作関数の定義です。TohoIn()の宣言を見てみると、(意味も考えたくない)長ったらしい3行からできていています。簡単に言うと入力命令と、それを整数に直す命令ですが、とりあえず、そういうものだと思って下さい。
注目して欲しい点は、次の2点、戻り値とその型(この場合int (注:staticは無視))です。TohoInはキーボードから入力された整数が戻り値です。static int TohoIn()のintは整数が戻り値であることを示します。戻り値を戻す命令は、関数中のreturn …です。returnの後の…が送り返される数値です。ですから、…の型が関数名の前(static の後)の型と同一になっていなくてはなりません。
関数TohoIn()の場合、関数に送る引数は、ありませんので()の中には何も書きません。
(2)引数を渡す関数
これは関数に引数を渡す例です。2つの整数引数を関数に送り、その2数の積を返す関数を宣言してみます。
static kakeru(int a, int b){ return a*b; } int m=5, m=7, c; c= kakeru(m, n); c= kakeru(5, 7); ß直上行と同じ結果になる
左が関数kakeruの宣言で、右がメインルーチンの一部で関数を呼んでいる例です。関数を呼ぶ場合の引数の与え方は、関数宣言の中で指定された通り(上の場合引数が2つで、引数の型はint)に与えます。引数の順番も大事で、関数宣言の通りの順で与える必要があります(上の例は積を返すので、逆でも結果は同じですが)。
5−4(もう分かった人は読まなくてよいたとえ話)
戻り値を返すか、返さないか、という観点から関数を分類し、たとえ話にします。関数はよく“専門家”に例えられますので、その筋で見直してみましょう。
第1のタイプは戻り値を返さないものです。例えば、関数内でデータを出力して終わる、といった場合です。これは専門家で言うと“廃棄物処理業者”みたいなものです。ごみを出すとどこかで処分されて、ごみを出した人には何も戻ってきません。
このタイプの関数を宣言する時は、関数名の前にstatic voidを付けます(下図)
class Mn_f1{ static void kansu(){ : } public static void main(… : kansu(); : }
第2のタイプは結果をmainに返すタイプで、“寿司職人”(飯とネタを“引数”としてもらい、寿司を返(return)してくる)って感じです。この場合は、関数宣言時に関数名の前に、
mainに返す値の型(例えばint)を付けます。また、mainに結果(値)を返すにはreturn命令を使います。
演習問題:
(アプリケーション)
(1) 2つの(整数)引数をもらい、それらの平均値(実数)を返す関数heikinを作れ。mainからheikinをheikin(3,7);という形で呼び、返ってきた数値を出力せよ。
(2)1つの数値を引数としてもらい、それを5倍した値を返す関数(gobai)を作り、mainから呼んで答えをもらいmain内で結果を出力せよ。gobaiに送る数は何でもよい。
(3) 2つの数値を入力し、大きい方の値を返す関数を作り、mainから呼んで、結果をmainで出力せよ。
(アニメーション)Math.~という組み込み関数を使う練習。
(4)サインカーブを描こう
(5)最初(100,100)の位置の丸を置く。これをランダムウオークさせよ。ランダムウオークとは、酔歩と訳されるもので、酔っ払いが千鳥足で歩くようにデタラメにあちこち移動するころです。
(ヒント:Math.random()は、これを呼ぶ度に0〜1の間の数値を返してくる。この戻り値を利用して(0~0.25なら上、0.25~0.5なら右、等)進行方向を決め、丸を移動させる)
(6)点(100,100)を中心に、半径10の円を半径80で円運動させよ。(ヒント:Math.sinとMath.cosに同じ角度を与えると円の位置が求まる)
(7)上の課題4,5で動くの円の数を2つに増やせ。
第6章 その他
本章では、緊急性に欠けるため今まで省いてきた命令やデータ構造を並べてみます。
もう、大分Javaに慣れてきたと思います。インターネットには沢山のよいJava解説サイトがあります。プログラム作成中不明な点や、忘れてしまったことは、サイトを探して解決するのが普通です。本章は、各項目に関して親切に解説していません。不明な点はネットのサイトを調べながら各項目を理解してみて下さい。
6−1 予め繰り返し回数が決められない場合の繰り返し命令while文
(while命令は無限ループに陥ることがよくあるので、初心者はできるだけ使わない方がよい)
while文は“条件が成立している限り繰り返す”という命令です。
while文は次の2種類があります。
(1) 繰り返し条件を、繰り返し処理の前に調べる
命令のフォーマットは、
while(条件式){繰り返し実行するプログラム}
です。
(2) 繰り返し条件を、繰り返し処理の後に調べる
命令のフォーマットは、
do{繰り返し実行するプログラム}while(条件式);
です。
6−2 数値によって場合分けするのに便利なswitch…case文
(プログラムが分かりにくくなるので、なるべく使わない方がよいと言われている)
命令のフォーマットは、
switch(変数名または式){
case(値1):その場合実行すべきプログラム
break;
case(値2):その場合実行すべきプログラム
break;
以下同様
default:以上のどれにも当てはまらない時のプログラム
}
6−3 配列の宣言
今までの配列宣言は、配列に初期値を書き込んだ形で宣言していた(とりあえず最も簡単な方法なので)。
初期値を与えないで、配列を宣言するには、以下のフォーマットにします。
次の図は、整数型で3つの要素を持つaという1次元配列を宣言する時の例です。
配列宣言は、別の方法もありますが、上のフォーマットに統一しましょう。何だか変な形ですが、理由は当面聞かないで下さい。これがいやなので今まで、直感的に分かりやすい、初期値をセットする方法で話を進めてきました。
6−3 文字列の扱い
今まで変数の型は数値を扱うintとdoubleだけを扱ってきました。しかし実際のプログラムでは文字列を扱うことが少なくありません。Javaは文字列を扱う高度な機能を持っています。あまりに高度すぎて使えないほどです。
混乱を避けるため、ここでは初心者のプログラムで必要な最低限の機能だけを紹介します。
(1) 文字列を格納する変数の型はStringです。
(2) 2つの文字列変数に文字列abcとdefを代入するには次のようにします。
String s1, s2;
s1= “abc”;
s2= “def”;
まとめて、String s= “abc”でもかまいません。
(3) キーボードから1行の文字列を入力するには次のようにします。
BufferedReader reader=new BufferedReader(new
InputStreamReader(System.in));
String
line=reader.readLine();
(変数lineに文字列が入力されます)何でこんな長ったらしいことをするのかは聞かないで下さい。
(4) 文字列の比較にはequals()を使い、次のようにします。
(s1とs2を比較する場合の例)
if( s1.equals(s2) ==true) {s1とs2が同じだった時の処理}
演習問題:
(アプリケーション)
(1) 数値999が入力されるまで、入力された数値を出力するプログラムを作れ。999が入力されたら、処理を終了。
(2)
数値を1から順に2、3、、、と加算していき、合計が333を超えた時に加えた数を出力せよ。
(3)
1〜7の数値を入力し1ならSun、2ならMon、3ならTueという風に出力せよ。
(4)
文字列の配列(要素数3)を用意する(簡単な文字列を入れておく)。キーボードから文字列を入力し、配列中で一致する文字列があれば、その配列要素番号を出力せよ。
(アニメーション)
(5)g.drawString(文字列, x座標, y座標);を使って画面に文字を表示してみよう。最初の引数(文字列)に文字列を”hello”のように直接書くほか、変数も指定できるのか確かめよう。
第7章 オブジェクト指向のイメージトレーニング
Javaはオブジェクト指向言語と言われます。いよいよオブジェクトに入るのですが、新しい概念なのでイメージトレーニングをしておいた方がよいと思います。本章は、最初にオブジェクトプログラムのイメージを示し、次にオブジェクトを2つの側面から説明します。
7−1 オブジェクトって何だ?
次の図は、オブジェクトプログラムのイメージを示しています。プログラムには魔法を使える1人の人(mainさん)がいます。その人は魔法のランプに呪文“new”と唱えることによりオブジェクトを作ります。オブジェクトは幻の世界のものです。
オブジェクトプログラムでは、現実の世界のものと、幻の世界のものをきちんと区別しておく必要があります。
(1) 現実の世界:現実の世界の住人はMainさん1人です。Mainさんは、自分の電卓、変数、関数などを持っています。これらの持ち物は現実世界のものです。プログラム上では現実世界のものには”static”と書いて幻の世界のものと区別します。
(2) 現実と幻の中間:mainさんは、忍術虎の巻を持っています。この虎の巻がclassです。Mainさんが魔法のランプにnewと声をかけるとオブジェクトができます。例えばセブンイレブン船橋店を作りたければ ”船橋店= new 7_11()”と呪文を唱えます。松屋柏店を作るには“柏店= new 松屋()”です。虎の巻はオブジェクトを作る設計図と考えてもよいし、オブジェクトを派遣する派遣会社と考えてもよいと思います。
(3) 幻の世界:オブジェクトは全て幻の世界です。全てのオブジェクトは、“データとそれに対する操作”が規定されています。“データとサービス”と考えた方が分かりやすいかもしれません。例えば、コンビ二は商品がデータで、サービスは“販売”、とか“仕入れ”です。銀行なら、銀行の総金額がデータで、サービスは“預け入れ”とか“引き出し”です。
正式には“データ”はフィールドと呼ばれ、“サービス”はメソッドと呼ばれます。
Mainさんは、呪文を唱え、自分に必要なオブジェクトを生成し、それに対してサービスを要求し(メソッドを呼んで)、目的の処理を実現します。
(細かなことは分からないでかまいませんが)
少し、オブジェクト指向プログラムのイメージが掴めましたか?
プログラミング言語の立場で見ると、オブジェクトは様々な側面を持っています。次節以降では、オブジェクトを2つの異なる側面から見てみようと思います。
7−2 オブジェクトをデータの型として見る見方
オブジェクトという言葉が始めて出てきたわけですが、実は、今までに(知らないうちに)いくつものオブジェクトを生成し使ってきています。例えば int a; 等と変数を宣言し使っていますが、この変数 a も整数(int)型のオブジェクトの一種です。Double b; なんて宣言した変数 b は実数(double)型のオブジェクトだったのです。
例えて言えば、intやdoubleはJavaの持っている既製品のデータ型で、変数はそのオブジェクトだったのです。既製品がある場合、業務用とか業界用(例えば美容師用鋏、生保用パソコン)があると一部の人達には便利です。
プログラムでも同様で、自分用の型を定義して、そのオブジェクトを作って使用するとプログラムが簡潔になります。自作の型の場合、“型はクラス”と呼ばれ、“変数はオブジェクト”と呼ばれます。先ずは、オブジェクトの雰囲気だけ。
(1) 既成のデータ型(int とdouble)の場合:
変数を、データ型(int と double)のオブジェクトと見た場合の両者の関係は以下のようになります。
(2) 自作のデータ型の場合:
某小規模塾(英語と数学しか教えず、同じ名前の人はいない)では、生徒の成績をプログラムで管理しています。この時、“成績表”というデータ型があると、プログラムはグッと楽になります。ここでは“成績表”という自作のデータ型(クラス)を基に、自作のデータ型(クラス)のイメージを示します。
“成績表”というクラスがあれば、変数(オブジェクト)は、簡単にいくらでも作れます。例えば藍ちゃんの成績表aiとか、健君の成績表kenとか。
(オブジェクトの心)成績表のオブジェクトには英語と数学の点が入っていないと困る。というわけで、オブジェクトには英語と数学の点数(データ)を入れる所が必要です。オブジェクトの持っているデータは
“フィールド” (別名“メンバー変数”)と呼ばれる場所に格納されています。
整数や実数では自然に+−×÷などの演算を行っていましたが、オブジェクトでは専用演算を定義します、これはメソッドと呼ばれます。上の例では、成績表に成績を書き込むためのkakikomi()というメソッドと、成績を読み出すためのyomidasi()を作りました。
フィールドとメソッドの定義には、既成の部品(int,やdoble)といった変数を使います。
(Seisekiクラスの宣言とオブジェクトの生成、利用の例)
上の図は、クラス(データ型)の定義(左上の四角)と、プログラム中でオブジェクトを生成する方法、メソッドの使い方(左下の四角)の例を示しています。
(次章に詳しく述べるので、完全に理解する必要はありませんが、雰囲気だけ分かってもらえれば幸いです)
自作の型(クラス)を作るにはクラスの定義が必要です。クラスではフィールドとメソッドを定義します。この場合、フィールドはeigoとsuugakuの成績なので、それぞれintで定義しています。メソッドkakikomiはeigo, suugakuへの点数の代入です。メソッドkakidasiはSystem.out.printによるeigo, suugakuの表示です。
プログラム内で、オブジェクトを使うには、先ず、クラスからオブジェクトを作る命令が必要で、これが newという命令です。ai= new Seiseki();でaiという成績表が出来上がります。メソッドはオブジェクト名の後に’.’を打ってメソッド名を書きます。例えば、aiの成績を表示するには、ai.kakidasi()とします。
もう一度、既成型と自作型(クラス)の対応を表にします。
クラス |
オブジェクト |
メソッド |
既成クラス int double |
個々の変数 |
+ - *
/ |
配列 |
個々の配列 |
要素同士の+-*/の他 .length |
自作クラス |
個々のオブジェクト |
.自作メソッド名() |
最後に、プログラムで使いそうなオブジェクトの例を3つ挙げます。
(1)貯金通帳
家族の貯金を管理するプログラムを作ろうとすると、通帳型があると便利です。オブジェクトは家族各人の通帳です。通帳を操作する演算(メソッド)は、”貯金預け入れ”と”引き出し”でしょう。フィールドは残金を入れておく整数型変数です。
(2)免許証
警察で免許証を管理するプログラムを作ろうとすれば、免許証型があると便利です。オブジェクトは各個人の免許証です。操作は、”番号から氏名を探す”、とか、”氏名から有効期限を調べる”といったものでしょう。フィールドは、番号を入れる整数変数、氏名を入れる文字列変数、生年月日を入れる整数変数などでしょう。
(4)○
実習では画面上を動き回る丸を複数作ってみます。各丸はオブジェクトです。丸のフィールドは、丸のx座標とy座標を記憶する変数で、丸の操作(メソッド)move()は丸のx、yを少し変更します。
7−3 オブジェクトを関数の進化型として見る見方
以前、関数は専門家(寿司職人)だという話をしました(参照5−4)。
main(){ x=kasan(4,5); System.out.println(x); } return c c= a+ b; a
b
ただ、関数(専門家)は材料をもらって寿司をつくることはできるが、材料を保存したりはできませんでした。簡単に言えば、入力値を計算し結果を垂れ流す専門家でした。
それでは、“荷物一時預り”のような専門家は作れません(何故なら、関数が前に呼ばれた時の結果などをしまって置けませんので)。
これを解決するためJavaでは、次に示す“クラス”と“オブジェクト”という概念を導入しました。
クラス=オブジェクト派遣(生成)会社。各店舗の倉庫とサービスのマニュアルがプログラムとしてここに書いてあります。倉庫は前節のフィールドを意味し、サービスは前節のメソッドに相当します。
例えば、“小僧寿しクラス”とか“吉野家クラス”では、チェーン店のサービスメニューを決めておきます。これがクラスで、この仕様に基づき各店舗を作ります。これがオブジェクトです(吉野家習志野店、吉野家赤坂店、がオブジェクトです)。
オブジェクト=倉庫を持った専門家チーム(冷蔵庫を持った、“すし職人”と“お勘定係”がチームを組んだもの、ってとこ)。各専門家は、オブジェクトの提供する“サービス”ということになり、これがメソッドです。
(あるクラスから作られるオブジェクトは、例えば小僧寿し大久保店、小僧寿し柏店、のように倉庫とサービス内容が同じです)
次に、一つの例を挙げてみます。
例)荷物を1つしか預かれない“荷物一時預り専門家集団”オブジェクトを考える
オブジェクト={荷物置き場:倉庫(フィールド)に対応;
預かりサービス:専門家1(メソッド)に対応;
荷物返却サービス:専門家2(メソッド)に対応;}
(注)専門家集団(チーム)の
各専門家は一つの機能しか担当しない。
プログラムにすると、
class Azukarigumi{
int okiba;
void azukarigakari(int ni){
okiba= ni;
}
int henkyakugakari(){
return okiba;
}
}
これはclass(クラス)ですので、“荷物預りチーム”派遣会社です。
main()の中では、新しい“専門家チーム派遣依頼”をnewで行い、チームにはmainの方で名前を付けます。
Azukarigumi azukarijo1=new Azukarigumi();
Azukarigumi azukarijo2=new Azukarigumi();
で2つのチーム(預り所)が派遣されました。
預り所1へ荷物(5)を預けるには、azukarijo1.azukarigakari(5);
預り所1から返してもらうには、modorini=azukarijo1.henkyakugakari();とします。
以上、なんとなくクラスとオブジェクトの雰囲気が伝わっているといいのですが。
第8章 オブジェクトプログラミング
オブジェクトプログラムの基本構成は、クラスの宣言(定義)部と、クラスのオブジェクトを生成し使用するメインプログラムからできています。
8−1 クラス宣言とオブジェクトの生成
ここでは、簡単な例を使ってオブジェクトプログラムの構造を見てみます。例題は、年齢を答えるDogというクラスを宣言し、2匹の犬(オブジェクトpochiとkuro)を作り、howold()と年齢を問いかけます。
<解法の手引き>
全章の例えで考えると:専門家(オブジェクト)は“年齢を答える(個々の)犬”です。犬派遣会社(クラス)には専門家(犬)の機能がプログラムされています。
専門家(犬)の倉庫は年齢を書いた変数です。
専門家のできるサービスは1つで、howold()という問に答えるだけです。
クラス(上図の場合Dog)定義は、次の3つの部分からできています。
(1) フィールド(上図の場合ageという変数)。
(2) “コンストラクタ”と呼ばれるフィールド初期化関数。コンストラクタはクラス名と同じ名の関数にすることになっています。フィールドを初期化する必要がない時は、コンストラクタは書かないでよいことになっています。(上の例では、年齢を引数で受け取り、ageに代入しています)
(3) メソッド(上の場合howold)のプログラム。下の例では、howoldはageを出力しています。
上図ではMn_1がメインプログラムです。mainでは2匹のDog(pochi3歳とkoro4歳)を作り、これらの犬にhowold()と質問しています。プログラムは答えを5,3と言ってくるはずです。
(コンストラクタに関する補足:
オブジェクトを生成する時、 “new オブジェクト名();”
というフォーマットを使いますが、この、オブジェクト名();はコンストラクタを、関数として呼んでいるのです。ですから、()の中はコンストラクタへの引数です。上の例の
new Dog(3);では、3が引数としてコンストラクタに送られます。
フィールドの初期設定が必要ない場合コンストラクタを書きませんが、その場合のnewではJavaが何もしないコンストラクタを影で作って実行していてくれるのです。)
(補足(使って欲しくないのですが、一応書いておきます):上のプログラムでは、メソッドに頼んでフィールドの値を聞き出していますが、メインの中から直接フィールドを構成する変数にアクセスすることもできます。その場合、
オブジェクト名.変数名
というフォーマットを使います。 .でオブジェクト名とメソッドをつなぐ形に似ていますが、メソッドの場合は最後に()が付きます。
上のプログラムでは、mainの中で、System.out.println(pochi.a);とすることになります。)
8−2 習うより慣れろ
クラスとオブジェクトは習うより慣れろですので、以下に問題と答えを並べてみます。最初は、答えを見ないで自分でやってみて下さい。最初は多分分からないでしょうが、慣れてくると簡単に答えられるようになります。
オブジェクト生成例題集
(1)constractorなしの例
1.1 "吠えろ"と言うと吠える、HoeInuという犬種があるとして、HoeInu2匹(pochiとkuro)作り吠えろ、と命令してみよう。
1.2 荷物一時預かり所があります。put(荷物)で荷物を預け、get()で預けた荷物を返してもらいます。預かり所(ekimaeという名の)を作り、数値を預け、次に返してもらいましょう。
1.3 スタックを作り、pushやpopをしてみよう。push(n)でnがプッシュされ、popでスタックのトップが返される。
(2) constractorのある例
2.1 howold()と聞くと、年齢を答える犬を2匹作り、歳を聞こう。constractorで年齢を登録しよう。
2.2 今どこを走っているかを知らせながら走る車がある。constractorで車番号を示す数字を登録。車はmove()という指示により10Kmづつ進み、現在位置と車番号を出力する。車を3台作り、move()で走らせてみよう。
2.3 C50という車種は最初50Km/sで走る。これにaccel()指示を出すと速度が10km/s早くなり、brake()命令を出すと速度が10km/s減る。C50を2台作り、加速したり減速したりして見よう。加、減速時に速度を出力しよう。constractorで車番号を示す数字を登録。
2.4 nanten()と聞くと成績を返してくる個人別成績カードがある。4人分の成績カードを作り、成績を聞いてみよう。constractorで成績を登録しておく。
解答
1.1 ............................
class HoeInu{
void hoero(){
System.out.println("wan");
}
}
public class C {
public static void main(String[] args){
HoeInu pochi= new HoeInu();
HoeInu koro= new HoeInu();
pochi.hoero();
koro.hoero();
}
}
1.2..............................
class Azukarijo{
int soko=0;
void put(int ni){
soko= ni;
}
int get(){
return soko;
}
}
public class C{
public static void main(String[] args){
int nimotu;
Azukarijo ekimae= new Azukarijo();
ekimae.put(5);
nimotu= ekimae.get();
System.out.println(nimotu);
}
}
1.3...............................
class Stack{
int st[]={0, 0, 0};
int pointer=0;
void push(int data){
st[pointer]= data;
pointer++;
}
int pop(){
pointer--;
return(st[pointer]);
}
}
public class C{
public static void main(String[] args){
int d;
Stack s= new Stack();
s.push(5);
s.push(7);
d= s.pop();
System.out.println(d);
d= s.pop();
System.out.println(d);
}
}
2.1...........................
class Dog {
int age;
Dog(int a){
age= a;
}
void howold(){
System.out.println(age);
}
}
public class I {
public static void main(String[] args){
Dog pochi= new Dog(5);
Dog koro= new Dog(3);
pochi.howold();
koro.howold();
}
}
2.2...........................
class Car{
int gou;
int where=0;
Car(int no){
gou= no;
}
void move(){
where= where+10;
System.out.println(gou+"gosha"+where);
}
}
public class C {
public static void main(String[] args){
Car mycar= new Car(1);
Car yourcar= new Car(2);
mycar.move();
mycar.move();
yourcar.move();
}
}
2.3...........................
class C50{
int gou;
int speed=50;
C50(int no){
gou= no;
}
void accel(){
speed= speed+10;
System.out.println(gou+"gosha"+speed);
}
void brake(){
speed= speed-10;
System.out.println(gou+"gosha"+speed);
}
}
public class C {
public static void main(String[] args){
C50 mycar= new C50(1);
C50 yourcar= new C50(2);
mycar.accel();
mycar.accel();
yourcar.brake();
}
}
2.4...........................
class Card{
int tensu;
Card(int t){
tensu= t;
}
int nanten(){
return tensu;
}
}
public class Seiseki{
public static void main(String args[]){
Card yamada= new Card(60);
Card sato= new Card(79);
Card tanaka= new Card(80);
Card ito= new Card(50);
int x=ito.nanten();
System.out.println(x);
}
}
演習問題
(アプリケーション)
(1)両替屋チェーン店D2Yはドルから円への両替だけを行う。D2Yは、
ryogae(int dollar)というメソッドを持ち、dollarに金額(ドル)を入れると円(整数)を返してくる。1ドルは100円とする。D2Yのニューヨーク店nyと、成田店nrtを作り、それぞれの店で100ドルを両替してもらうプログラムを作れ。
D2Yはクラスで、nyとnrtがD2Yのオブジェクト(インスタンス)である。
<方針>:main()の中でnewを使いnyとnrtを作り、ryogae(100)を行う。両替で替えてもらった金額(yen)はmain()内で出力する。
(2)クラスFIFOとLIFOを作れ。これらは共にint data[3]の配列を用意し、put(…)でデータを書き込み、get()でデータを取り出す(オーバフローと、空からのget()はないように使う)。
FIFO,LIFO共put(…)では配列の左(data[0])
から詰めていく。int indexはput(…)でデータ
を書き込む位置を指定する(最初は0、右図は
データが1つ書き込まれている状態)。
get()の場合、FIFOとLIFOで処理が異なる。
LIFOではindex-1の指す配列の中身を返し、
FIFOではdata[0]を取り出し、左端が空になるので配列内を左にシフトする。
(FIFO及びLIFOは別のクラスにし、get()とput(…)をメソッドにする)
main()では、get()で取り出した中身を出力するようにし、次の命令を実行する。
fifo.put(6); fifo.put(7);fifo.put(8); fifo.get();fifo.get(); fifo.get();
lifo.put(1); lifo.put(2);lifo.put(3); lifo.get();lifo.get(); lifo.get();
プログラムの構造
(アプレット)
(3)クラスBallを定義せよ。フィールドはボールのx座標xとy座標y。メソッドはmove()はxを+5し、ボールの位置を右にシフトする。y座標はコンストラクタで設定する。3つのボールが右に動くアニメを作れ。