今、次のようなプログラムを考えます。
/* 1*/ class NameTag1 { // 名札1 /* 2*/ public static void main (String[] args) { /* 3*/ System.out.println("-------------------------"); /* 4*/ System.out.println("-------------------------"); /* 5*/ System.out.println("No."); /* 6*/ System.out.println("-------------------------"); /* 7*/ System.out.println("Name"); /* 8*/ System.out.println(); /* 9*/ System.out.println("-------------------------"); /* 10*/ System.out.println("-------------------------"); /* 11*/ } /* 12*/ }
asiaa1:~/comp2b b08a001$ java NameTag1 ------------------------- ------------------------- No. ------------------------- Name ------------------------- ------------------------- asiaa1:~/comp2b b08a001$
3行目、4行目、6行目などに、罫線を出力するという、まったく同じ処理が繰り返されています。 これらの処理に名前をつけ、その名前で処理が表せると、プログラムが読みやすく、かつ書きやすくなります。 メソッドというものを用いると、そのようなことができます。 なお、メソッドには「インスタンスメソッド」というものと「クラスメソッド」というものがあります。 今日はクラスメソッドのみ扱います。
メソッド ( method ) とは、処理のまとまりに名前をつけたプログラム単位です。 メソッドを使うためには、プログラムの中でメソッドを定義しなくてはいけません。 メソッドの定義は次のような形をとります。
static void methodname () { statement; ... }
これによって、処理のまとまり
statement
;
...
に
methodname
という名前がつきます。
定義したメソッドを使うには、プログラムに次のような文を書きます。 これを メソッド呼出し ( method call ) とよびます。
methodname();
プログラムの中にメソッド呼出しがあると、実行の流れは次の図のようになります。 メソッド呼出し f () を実行するとき、メソッド f の定義の内容を実行し、それが終わったら、メソッド呼出しの次から実行します。
上記のプログラムの場合、次のようになります。 罫線を出力するという処理に、 rule という名前をつけています。 メソッド呼出し rule () を実行すると、罫線が出力されます。
/* 1*/ class NameTag2 { // 名札2 /* 2*/ public static void main (String[] args) { /* 3*/ rule(); // メソッド呼出し /* 4*/ rule(); // メソッド呼出し /* 5*/ System.out.println("No."); /* 6*/ rule(); // メソッド呼出し /* 7*/ System.out.println("Name"); /* 8*/ System.out.println(); /* 9*/ rule(); // メソッド呼出し /* 10*/ rule(); // メソッド呼出し /* 11*/ } /* 12*/ static void rule () { // メソッド定義 /* 13*/ System.out.println("-------------------------"); /* 14*/ } /* 15*/ }
メソッドは、いくつも定義することができます。 次の例では、罫線を出力するメソッド rule と、二重の罫線を出力するメソッド doubleRule を定義しています。
/* 1*/ class NameTag3 { // 名札3 /* 2*/ public static void main (String[] args) { /* 3*/ doubleRule(); /* 4*/ System.out.println("No."); /* 5*/ rule(); /* 6*/ System.out.println("Name"); /* 7*/ System.out.println(); /* 8*/ doubleRule(); /* 9*/ } /* 10*/ static void rule () { // 罫線 /* 11*/ System.out.println("-------------------------"); /* 12*/ } /* 13*/ static void doubleRule () { // 二重の罫線 /* 14*/ System.out.println("-------------------------"); /* 15*/ System.out.println("-------------------------"); /* 16*/ } /* 17*/ }
上記の例では、罫線を出力するメソッド rule と、二重の罫線を出力するメソッド doubleRule を定義しました。 このまま、三重の罫線、四重の罫線、…と定義するのは面倒です。 できれば、メソッドに変数 n を入力して、 n 重の罫線を出力するメソッドにしたいものです。
メソッドには引数を与えることができます。 引数 ( argument ) とは、メソッドに対する入力データだと思ってください。
引数を持つメソッドは次のように定義されます。 argument の部分に、引数を表す変数を書きます。
static void methodname (int argument, ...) { statement; ... }
このようなメソッドを呼び出すには、次のように書きます。 argument の部分に、引数となる式を書きます。
methodname(argument, ...);
メソッド定義の引数を 仮引数 ( formal argument ) とよび、メソッド呼出しの引数を 実引数 ( actual argument ) とよびます。 メソッドは呼び出されると、仮引数(変数)に実引数(式)の値が代入され、メソッド定義の内容が実行されます。
次の例では、 n 重の罫線を出力するメソッド multiRule を定義しています。 メソッド呼出し multiRule (2) が実行されると、メソッド定義の仮引数 n に実引数の値2が代入され、罫線の出力を2回繰り返すようにメソッドが実行されます。 なお、メソッド定義の中でも変数が宣言できることに注意してください。 (11行目)
/* 1*/ class NameTag4 { // 名札4 /* 2*/ public static void main (String[] args) { /* 3*/ multiRule(2); // n = 2 /* 4*/ System.out.println("No."); /* 5*/ multiRule(1); // n = 1 /* 6*/ System.out.println("Name"); /* 7*/ System.out.println(); /* 8*/ multiRule(2); // n = 2 /* 9*/ } /* 10*/ static void multiRule (int n) { // n重の罫線 /* 11*/ int i; // メソッド定義の中で使う /* 12*/ for (i = 0; i < n; i++) { /* 13*/ System.out.println("-------------------------"); /* 14*/ } /* 15*/ } /* 16*/ }
メソッドを呼び出すとき、仮引数には実引数の値が代入されます。 詳しく言うと、呼出しの際、仮引数の変数が用意され、そこに実引数の値のコピーが格納されます。 このような呼び出し方を、 値呼出し ( call by value ) とよびます。
メソッドは、まとまった処理をするだけでなく、何らかの計算をして、その値を呼び出し側に返すこともできます。 そのような値を、メソッドの 返り値 ( return value ) とよびます。 返り値は、メソッドの出力データと考えてください。
一般的なプログラミングの用語では、値を返さないプログラム単位を 手続き ( procedure )と呼び、値を返すプログラム単位を 関数 ( function )と呼びます。 Javaでは、手続きも関数もメソッドで実現します。
整数(
int
型)を返り値に持つメソッドは、次のように定義されます。
static int methodname (int argument, ...) { statement; ... }
これまでの、返り値を持たないメソッド定義での
void
の代わりに、
int
と書きます。
この定義の中に、少なくとも一つ
return
文を書きます。
return
文は次のような形をとり、式
expression
の値がこのメソッドの返り値になります。
return expression;
返り値を持つメソッドは、次のような式で呼び出します。
methodname(argument, ...)
式の中にメソッド呼出しがあると、メソッド定義の内容が実行されます。
そして、その中の
return
文が実行されると、メソッドの実行は終了され、
return
文の式の値が呼び出し側に返されます。
次の例では、引数の2乗を返すメソッド square と、引数の3乗を返すメソッド cube を定義しています。
/* 1*/ class SquareCubeTest { // 2乗と3乗のテスト /* 2*/ public static void main (String[] args) { /* 3*/ System.out.println(square(100)); // メソッド呼出し /* 4*/ System.out.println(cube(100)); // メソッド呼出し /* 5*/ } /* 6*/ static int square (int x) { // メソッド定義 /* 7*/ return x * x; // 値を返す /* 8*/ } /* 9*/ static int cube (int x) { // メソッド定義 /* 10*/ return x * x * x; // 値を返す /* 11*/ } /* 12*/ }
asiaa1:~/comp2b b08a001$ java SquareCubeTest 10000 1000000 asiaa1:~/comp2b b08a001$
次の例では、2つの数のうち、大きい方を返すメソッド
max
と、小さい方を返すメソッド
min
を定義しています。
引数が複数あるときは、コンマで区切ります。
仮引数の
int
を一つにまとめることはできません。
/* 1*/ class MaxMinTest { // 最大値と最小値のテスト /* 2*/ public static void main (String[] args) { /* 3*/ System.out.println(max(100, 200)); // 実引数が2つ /* 4*/ System.out.println(min(100, 200)); // 実引数が2つ /* 5*/ } /* 6*/ static int max (int m, int n) { // 仮引数が2つ /* 7*/ if (m > n) { /* 8*/ return m; /* 9*/ } else { /* 10*/ return n; /* 11*/ } /* 12*/ } /* 13*/ static int min (int m, int n) { // 仮引数が2つ /* 14*/ if (m < n) { /* 15*/ return m; /* 16*/ } else { /* 17*/ return n; /* 18*/ } /* 19*/ } /* 20*/ }
asiaa1:~/comp2b b08a001$ java MaxMinTest 200 100 asiaa1:~/comp2b b08a001$
注意:
返り値を持たないメソッドでも
return
文が使えます。
この場合、式を抜いた
return;
という形になります。
メソッドの実行中に
return
文を実行すると、そこでメソッドの実行を終了します。
メソッドの例として、はじめに m の n 乗を計算するメソッド power を定義します。 ここで、 n ≧0 と仮定します。
メソッド
power
の引数は、
m
と
n
です。
このメソッドは整数を返すので、
static int
と指定します。
メソッド定義では、まず、変数
result
を宣言し、1で初期化します。
そして、
for
文の中で、
result
の値を
n
回
m
倍します。
最後に、
result
の値を
return
で返します。
メソッド呼出しでは、例として、 power (2, 5), power (5, 2), power (3, 3) の3つの式について、式自身とその値を出力します。
プログラムは次の通りです。
/* 1*/ class PowerTest { // べき乗のテスト /* 2*/ public static void main (String[] args) { /* 3*/ System.out.println("power(2, 5) = " + power(2, 5)); /* 4*/ System.out.println("power(5, 2) = " + power(5, 2)); /* 5*/ System.out.println("power(3, 3) = " + power(3, 3)); /* 6*/ } /* 7*/ static int power (int m, int n) { // mのn乗 /* 8*/ int i, result = 1; /* 9*/ for (i = 0; i < n; i++) { // n回m倍する /* 10*/ result = result * m; /* 11*/ } /* 12*/ return result; /* 13*/ } /* 14*/ }
asiaa1:~/comp2b b08a001$ java PowerTest power(2, 5) = 32 power(5, 2) = 25 power(3, 3) = 27 asiaa1:~/comp2b b08a001$
次の例は、階乗を計算するメソッド fact です。 ここで n の階乗とは、 n ! と表され、
と定義されるものです。 ( n ≧0 と仮定します。)
メソッド
fact
の引数は
n
です。
このメソッドは整数を返すので、
static int
と指定します。
メソッド定義では、まず、変数
result
を宣言し、1で初期化します。
そして、
for
文の中で、
result
の値を1倍し、2倍し、…、
n
倍します。
最後に、
result
の値を
return
で返します。
メソッド呼出しでは、例として、 fact (4), fact (5), fact (6) の3つの式について、式自身とその値を出力します。
プログラムは次の通りです。
/* 1*/ class FactTest { // 階乗のテスト /* 2*/ public static void main (String[] args) { /* 3*/ System.out.println("fact(4) = " + fact(4)); /* 4*/ System.out.println("fact(5) = " + fact(5)); /* 5*/ System.out.println("fact(6) = " + fact(6)); /* 6*/ } /* 7*/ static int fact (int n) { // nの階乗 /* 8*/ int i, result = 1; /* 9*/ for (i = 1; i <= n; i++) { // 1倍2倍...n倍する /* 10*/ result = result * i; /* 11*/ } /* 12*/ return result; /* 13*/ } /* 14*/ }
asiaa1:~/comp2b b08a001$ java FactTest fact(4) = 24 fact(5) = 120 fact(6) = 720 asiaa1:~/comp2b b08a001$
上記のメソッド square や cube を参考にして、円、ドル、ユーロの間で両替をするメソッドを定義して、それらを呼び出すプログラムを作成してください。 1ドルは100円、1ユーロは140円とし、小数点以下は切り捨てます。
円をドルに両替する場合は、メソッドの名前を
yenToDollar
とし、引数を
yen
とします。
このメソッドは整数を返すので、
static int
と指定します。
メソッド定義では、式
yen
/ 100 の値を
return
で返します。
ドルを円に両替するメソッド dollarToYen , 円をユーロに両替するメソッド yenToEuro , ユーロを円に両替するメソッド euroToYen も同様に定義します。
メソッド呼出しでは、例として、 yenToDollar (7000), dollarToYen (70), yenToEuro (7000), euroToYen (50) の4つの式について、式自身とその値を出力します。
asiaa1:~/comp2b b08a001$ java YenDollarEuro yenToDollar(7000) = 70 dollarToYen(70) = 7000 yenToEuro(7000) = 50 euroToYen(50) = 7000 asiaa1:~/comp2b b08a001$
余力のある人は、ドルをユーロに両替するメソッドと、ユーロをドルに両替するメソッドも定義してください。 (小数を使うとエラーになるので、数式を工夫してください。)
asiaa1:~/comp2b b08a001$ java YenDollarEuro2 yenToDollar(7000) = 70 dollarToYen(70) = 7000 yenToEuro(7000) = 50 euroToYen(50) = 7000 dollarToEuro(70) = 50 euroToDollar(50) = 70 asiaa1:~/comp2b b08a001$
今日の演習8の答案(Javaプログラム)をメールで提出してください。 差出人は学内のメール・アドレス(b08a001@cis.twcu.ac.jpなど)とし、宛先はkonishi@cis.twcu.ac.jpとします。 メールの本文には、学生番号、氏名、科目名、授業日(6月12日)を明記してください。