今、次のようなプログラムを考えます。
/* 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*/ }
24102a1:java1 k16x1001$ java NameTag1 ------------------------- ------------------------- No. ------------------------- Name ------------------------- ------------------------- 24102a1:java1 k16x1001$
3行目、4行目、6行目などに、罫線を出力するという、まったく同じ処理が繰り返されています。 これらの処理に名前をつけ、その名前で処理が表せると、プログラムが読みやすく、かつ書きやすくなります。 メソッドというものを用いると、そのようなことができます。 なお、メソッドには「インスタンス・メソッド」というものと「クラス・メソッド」というものがあります。 今日はクラス・メソッドのみ扱います。
メソッド ( method )とは、処理のまとまりに名前をつけたプログラム単位です。 メソッドを使うためには、プログラムの中でメソッドを定義しなくてはいけません。 メソッドの定義は次のような形をとります。
static void メソッド名 () { 文; ... }
これによって、処理のまとまり「 文 」、...に「 メソッド名 」という名前がつきます。
定義したメソッドを使うには、プログラムに次のような文を書きます。 これを メソッド呼出し ( method call )とよびます。
メソッド名();
プログラムの中にメソッド呼出しがあると、実行の流れは次の図のようになります。 メソッド呼出し m ()を実行するとき、メソッド m の定義の内容を実行し、それが終わったら、メソッド呼出しの次から実行します。
上記のプログラムの場合、次のようになります。 罫線を出力するという処理に、 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 )とは、メソッドに対する入力データだと思ってください。
整数(int型)の引数を持つメソッドは次のように定義されます。 「 引数 」の部分に、引数を表す変数を書きます。
static void メソッド名 (int 引数, ...) { 文; ... }
引数が実数(double型)ならば、
int
の代わりに
double
と書きます。
このようなメソッドを呼び出すには、次のように書きます。 「 引数 」の部分に、引数となる式を書きます。
メソッド名(引数, ...);
メソッド定義の引数を 仮引数 ( 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*/ }
メソッドは、まとまった処理をするだけでなく、何らかの計算をして、その結果を呼び出し側に返すこともできます。 そのような値(計算結果)を、メソッドの 返り値 ( return value )または 戻り値 とよびます。 返り値は、メソッドの出力データと考えてください。
一般的なプログラミングの用語では、値を返さないプログラム単位を 手続き ( procedure )と呼び、値を返すプログラム単位を 関数 ( function )と呼びます。 Javaでは、手続きも関数もメソッドで実現します。
整数(int型)の返り値を持つメソッドは、次のように定義されます。
static int メソッド名 (int 引数, ...) { 文; ... }
これまでの、返り値を持たないメソッド定義での
void
の代わりに、
int
と書きます。
返り値が実数(double型)ならば、
void
の代わりに
double
です。
この定義の中に、少なくとも一つreturn文を書きます。 return文 は次のような形をとり、「 式 」の値がこのメソッドの返り値になります。
return 式;
返り値を持つメソッドは、次のような式で呼び出します。
メソッド名(引数, ...)
式の中にメソッド呼出しがあると、メソッド定義の内容が実行されます。 そして、その中のreturn文が実行されるとメソッドは終了し、return文の式の値が呼び出し側に返されます。
次の例では、引数の2乗を返すメソッド square と、引数の3乗を返すメソッド cube を定義しています。
/* 1*/ class SquareCubeTest { // 2乗と3乗のテスト /* 2*/ public static void main (String[] args) { /* 3*/ System.out.println("square(100) = " + square(100)); // メソッド呼出し /* 4*/ System.out.println("cube(100) = " + 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*/ }
24102a1:java1 k16x1001$ java SquareCubeTest square(100) = 10000 cube(100) = 1000000 24102a1:java1 k16x1001$
次の例では、2つの引数のうち、大きい方を返すメソッド
max
と、小さい方を返すメソッド
min
を定義しています。
引数が複数あるときは、コンマで区切ります。
仮引数の
int
を一つにまとめることはできません。
/* 1*/ class MaxMinTest { // 最大値と最小値のテスト /* 2*/ public static void main (String[] args) { /* 3*/ System.out.println("max(100, 200) = " + max(100, 200)); // m = 100, n = 200 /* 4*/ System.out.println("min(100, 200) = " + min(100, 200)); // m = 100, n = 200 /* 5*/ } /* 6*/ static int max (int m, int n) { // int m, n はエラー /* 7*/ if (m > n) { /* 8*/ return m; /* 9*/ } else { /* 10*/ return n; /* 11*/ } /* 12*/ } /* 13*/ static int min (int m, int n) { // int m, n はエラー /* 14*/ if (m < n) { /* 15*/ return m; /* 16*/ } else { /* 17*/ return n; /* 18*/ } /* 19*/ } /* 20*/ }
24102a1:java1 k16x1001$ java MaxMinTest max(100, 200) = 200 min(100, 200) = 100 24102a1:java1 k16x1001$
注意:
返り値を持たないメソッドでも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 *= m; /* 11*/ } /* 12*/ return result; /* 13*/ } /* 14*/ }
24102a1:java1 k16x1001$ java PowerTest power(2, 5) = 32 power(5, 2) = 25 power(3, 3) = 27 24102a1:java1 k16x1001$
次の例は、階乗を計算するメソッド 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 *= i; /* 11*/ } /* 12*/ return result; /* 13*/ } /* 14*/ }
24102a1:java1 k16x1001$ java FactTest fact(4) = 24 fact(5) = 120 fact(6) = 720 24102a1:java1 k16x1001$
上記のメソッド square や cube を参考にして、円、ドル、ユーロの間で両替をするメソッドを定義して、それらを呼び出すプログラムを作成してください。 1ドルは110.0円、1ユーロは130.0円とします。
円をドルに両替する場合は、メソッドの名前を
yenToDollar
とします。
このメソッドの引数は、実数
yen
です。
このメソッドは実数を返すので、
static double
と指定します。
メソッド定義では、式
yen
/110.0の値をreturn文で返します。
ドルを円に両替するメソッド dollarToYen , 円をユーロに両替するメソッド yenToEuro , ユーロを円に両替するメソッド euroToYen も同様に定義します。
メソッド呼出しでは、例として、 yenToDollar (1430.0), dollarToYen (13.0), yenToEuro (1430.0), euroToYen (11.0) の4つの式について、式自身とその値を出力します。
24102a1:java1 k16x1001$ java YenDollarEuro yenToDollar(1430.0) = 13.0 dollarToYen(13.0) = 1430.0 yenToEuro(1430.0) = 11.0 euroToYen(11.0) = 1430.0 24102a1:java1 k16x1001$
余力のある人は、ドルをユーロに両替するメソッドと、ユーロをドルに両替するメソッドも定義してください。
24102a1:java1 k16x1001$ java YenDollarEuro2 yenToDollar(1430.0) = 13.0 dollarToYen(13.0) = 1430.0 yenToEuro(1430.0) = 11.0 euroToYen(11.0) = 1430.0 dollarToEuro(13.0) = 11.0 euroToDollar(11.0) = 13.0 24102a1:java1 k16x1001$
今日の演習11の答案(Javaプログラム)をメールで提出してください。 差出人は学内のメール・アドレス(学生番号@cis.twcu.ac.jp)とし、宛先はkonishi@cis.twcu.ac.jpとします。 メールの本文には、学生番号、氏名、科目名、授業日(12月14日)を明記してください。