9. 1 復習(1) 9. 2 オブジェクト 9. 3 インスタンス変数 9. 4 練習問題 9. 5 インスタンスを作る 9. 6 練習問題 9. 7 インスタンスのメソッド 9. 8 練習問題 9. 9 クラス変数とクラスメソッド 9.10 宿題 9.11 おまけ
プログラミングの基本的な概念を第8週までで一通り説明しました。これまで に出てきた概念は、Java 言語だけに限らず、他の言語でプログラムを書く場 合にも必要になるものです。今週以降は、復習の節を設けますので、ここまで のところに不安がある人は、習ったことを確認して完全に理解するようにして ください。 |
Java 言語のプログラムはクラスとメソッドで出来ています。メソッドの中で は普通上から下に順に実行していきますが、実行の流れを変える文がいくつか あります。
[問]1から100までの数字のうち、偶数だけの合計を求めるにはどうすればよ
いでしょう?for文を使う方法、while文を使う方法、
for文とif文を使う方法など、何種類もの解き方がありま
す。いくつ考えつきますか?
プログラミング言語にはいろいろな種類がありますが、その中にオブジェ
クト指向プログラミング言語(object oriented programming language)
と呼ばれるものがあり、Java 言語もその一つです。これは、計算の単位とし
てオブジェクトと呼ばれるものを使います。
オブジェクト(object)とは、いくつかのデータやメソッドをまと
めて一塊にしたものです。小さなプログラムを作るときはそれほど便利さを感
じませんが、大きなプログラムを作るときは、オブジェクトに分割することに
よって見通しが良くなるので重要です。
オブジェクトは、直接ソースファイルの中に書くものではありません。ソース
ファイルの中に書くのはクラスです。オブジェクトは、クラスを基にして作り
ます。例えば、タコ焼の鉄板をクラスとすると、それで焼いたタコ焼がオブジェ
クトになります。クラス A を基にして作ったオブジェクトを、クラ
スA のインスタンス(instance)と呼びます。一つのクラ
スから、いくつでもインスタンスを作ることができます。
それぞれのインスタンスは、データを覚えておくための変数をいくつか持つこ
とができます。これをインスタンス変数(instance variable)と呼
びます。同じクラスのインスタンスは、同じ名前のインスタンス変数を持ちま
すが、変数が記憶しているデータはインスタンスごとに違います。
インスタンス変数の変数宣言は、クラス宣言の本体の中で、どのメソッド宣言
にも入らない場所で行います。例えば、第1週の例題
9.2 オブジェクト
9.3 インスタンス変数
class Count extends SfcDoNothing { int x = 0; void sfcProcess () { x = x + 1; sfcOutput(Integer.toString(x)); } } |
class Precision extends SfcDoNothing { void sfcProcess () { double x = 0.0; for (int i = 1000000; i >= 1; i = i - 1) { x = x + 1.0 / i; } sfcOutput(Double.toString(x)); } } |
インスタンス変数 | ローカル変数 | 仮引数 | |
---|---|---|---|
変数宣言 | クラス宣言の中でメソッド宣言の外 | メソッ ド宣言の中 | メソッド名の直後の括弧の中 |
有効範囲 | プログラム全体(注1) | 変数宣言を含む最も内側 のブロックだけ(注2) | そのメソッドだけ |
初期値 | インスタンスが作られた時に初期値が代入される | 変数宣言が実行されるときに初期値が代入される | メソッド 呼び出しの時に実引数が代入される |
存続期間 | ずっと存在する | ブロックの実行が終了す ると消えてしまう(注2) | メソッドの実行が終了すると消えてしまう |
(注1)そのインスタンス自身が使うときは変数名だけを書きますが、他のイン スタンスで使うときは、
インスタンス.変数名と書きます。
(注2)for の直後の括弧の中で宣言された変数は、有効範囲がその
for 文全体で、存続期間はその for 文が終了するまでで
す。
9.4 練習問題
上の第1週の例題で、変数宣言の位置を次のように変えるとどうなるでしょう
か。ボタンをクリックしたときの動作を予想し、実際にそうなるか確かめなさ
い。
class Count extends SfcDoNothing { void sfcProcess () { int x = 0; x = x + 1; sfcOutput(Integer.toString(x)); } } |
今まで練習で書いてきたクラスは、SfcExample1 または SfcExample2 がインスタンスを一つだけ作って、その中のメソッド を呼び出してくれていました。今度は自分でインスタンスを作る練習をしましょう。
クラス A のインスタンスを新しく作るには、
new A(引数)と書きます。引数のところには、そのインスタンスに与えるデータを書きます。 同じ鉄板を使って焼くタコ焼でも、中にはタコを入れたり、イカを入れたりで きます。
作ったインスタンスを記憶しておくには、そのクラスに対応する型の変数に代 入しなければなりません。クラス A のインスタンスを作って、変数 x に覚えておくには、次のようにします。
A x = new A(引数);違うクラスの型の変数に代入することはできません。お好み焼きの皿にタコ焼 を盛り付けてはいけません。
![]() ![]() |
先週の国別の人口と GDP のデータを考えてみましょう。
Country | Total Population (in thousands, 1997 est.) | GDP (million US$, 1995) |
United Kingdom | 58201 | 1102658 |
Egypt | 64466 | 60436 |
India | 960178 | 338785 |
Japan | 125638 | 5217573 |
Australia | 18250 | 358147 |
United States of America | 271648 | 6954787 |
Brazil | 163132 | 717187 |
class Nation { String name; int population; int gdp; }これだけでも、new Nation() とすれば、インスタンスを作ることが できます。しかし、そのインスタンスの変数の中身は空っぽなので、役に立ち ません。後から変数それぞれに代入していくこともできますが、それではかえっ て面倒です。そこで、クラスの中にコンストラクタ(constructor) を宣言して、インスタンスを作るときにその中身も作るようにします。
1 2 3 4 5 6 7 8 9 10 11 |
class Nation { String name; int population; int gdp; Nation(String n, int p, int g) { name = n; population = p; gdp = g; } } |
クラス Nation を使って、グラフを描くクラス Nations を書いてみましょう。ファイル NationGraph.java の内容を次のように 書いてください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
import java.awt.*; class Nation { String name; int population; int gdp; Nation(String n, int p, int g) { name = n; population = p; gdp = g; } } class NationGraph extends SfcDoNothing { void sfcDraw(Graphics g) { Nation data[] = new Nation[7]; data[0] = new Nation("UK", 58201, 1102658); data[1] = new Nation("Egypt", 64466, 60436); data[2] = new Nation("India", 960178, 338785); data[3] = new Nation("Japan", 125638, 5217573); data[4] = new Nation("Australia", 18250, 358147); data[5] = new Nation("USA", 271648, 6954787); data[6] = new Nation("Brazil", 163132, 717187); for (int i = 0; i < data.length; i = i + 1) { g.setColor(Color.black); g.drawString(data[i].name, 10, i*30+30); g.setColor(Color.blue); g.fillRect(80, i*30+15, data[i].population*200/1000000, 10); g.setColor(Color.green); g.fillRect(80, i*30+25, data[i].gdp*200/7000000, 10); } } } |
これを
% javac NationGraph.javaでコンパイルすると、NationGraph.class と Nation.class という二つのクラスファイルができます。実行すると きは、SfcDoNothing を拡張したクラスを指定するので、
% java sfcExample2 NationGraphとします。
Nation クラスのデータをソートするプログラムを作りましょう。
Boolean CompareNation(Nation x, Nation y, String key) { if (key.equals("name")) { ......
int findHead(Nation a[], int n, String key) { Nation head = a[n]; int index = n; for (int i = .....
void swap(Nation a[], int n, int m) { Nation tmp = a[n]; ........
![]() ![]() ![]() |
インスタンスは、変数の中にデータを記憶するだけでなく、メソッドを実行す ることで計算も行います。これまではインスタンスが1個しかなかったので、 どのインスタンスのメソッドかということは考えませんでしたが、メソッドを 実行するときは、必ずそれを実行しているインスタンスが存在します。
国別の、一人当たり GDP を計算するメソッドを追加しましょう。
class Nation { String name; int population; int gdp; Nation(String n, int p, int g) { name = n; population = p; gdp = g; } int gdpPerPerson() { return gdp/population; } }gdpPerPerson を呼び出すときは、実行するインスタンスを指定して、
インスタンス.gdpPerPerson()とします。引数がないことに注意してください。計算に必要な人口と GDP の 値は、インスタンスの中にある変数の値を使います。先ほどのグラフの、GDP の代わりに一人当たり GDP を表示するプログラムは次のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
import java.awt.*; class Nation { String name; int population; int gdp; Nation(String n, int p, int g) { name = n; population = p; gdp = g; } int gdpPerPerson() { return gdp/population; } } class NationGraph extends SfcDoNothing { void sfcDraw(Graphics g) { Nation data[] = new Nation[7]; data[0] = new Nation("UK", 58201, 1102658); data[1] = new Nation("Egypt", 64466, 60436); data[2] = new Nation("India", 960178, 338785); data[3] = new Nation("Japan", 125638, 5217573); data[4] = new Nation("Australia", 18250, 358147); data[5] = new Nation("USA", 271648, 6954787); data[6] = new Nation("Brazil", 163132, 717187); for (int i = 0; i < data.length; i = i + 1) { g.setColor(Color.black); g.drawString(data[i].name, 10, i*30+30); g.setColor(Color.blue); g.fillRect(80, i*30+15, data[i].population*200/1000000, 10); g.setColor(Color.orange); g.fillRect(80, i*30+25, data[i].gdpPerPerson()*200/80, 10); } } } |
変数宣言やメソッド宣言の前に static と書くと、その変数やメソッ ドはインスタンスにではなく、クラスに属することになります。そのような変 数、メソッドを使うときは、
クラス名.変数名および
クラス名.メソッド名(引数)と書きます。例えば、Integer.parseInt() は、Integer クラスに属する parseInt メソッドです。クラスに属する変数、メ ソッドは、インスタンスを作らなくても使えます。
次のような入試結果があるとします。
受験番号 | 英語 | 数学 | 小論文 |
---|---|---|---|
1001 | 61 | 75 | 50 |
1002 | 80 | 52 | 70 |
1003 | 73 | 68 | 80 |
1004 | 40 | 52 | 40 |
1005 | 56 | 82 | 60 |
各受験生の得点は、英語と数学のどちらか良い方と小論文の合計点であるとし
ます。各受験生を表すクラスと、得点を計算するメソッドを作り、そのインス
タンスを使って得点の高い順にソートするプログラムを作りなさい。
9.11 おまけ
StringTokenizer クラスを使うと、文字列をコンマなどの区切りで
分解して取り出すことができます。使い方は次の通りです。
これを使って、X 座標、Y 座標、半径を入力し、その位置に円を描くプログラ
ムを作りなさい。
import java.util.StringTokenizer;
を書きます。
new StringTokenizer(String s, String separator);
s は分解したい文字列、separator は区切り文字です。例
えば、"100,200,40" という文字列をコンマで区切って分解したいと
きは、
StringTokenizer st = new StringTokenizer("100,200,40", ",");
とします。
String nextToken()
上の例では、最初に st.nextToken() を実行すると、
"100" が、2回目に実行すると "200" が、3回目に実行す
ると "40" が返ってきます。
慶應義塾大学の授業以外での無断利用、複製はご遠慮下さい。
Copyright (c) 1999 慶應義塾大学