Java言語は、オブジェクト指向プログラミング(object-oriented programming)という考え方に基づいています。 オブジェクト指向とは、簡単に言えば、操作よりもデータに注目するということです。 Javaらしいプログラムを書くには、オブジェクト指向プログラミングを理解する必要があります。 ただし、オブジェクト指向プログラミングは、比較的最近提案されたものであり、それほどやさしくありません。
Java言語では、オブジェクト指向に基づかない古典的な手法でも、ある程度プログラムが書けます。 この授業では、はじめに古典的な手法を紹介し、少しずつオブジェクト指向の考え方に慣れることにします。
今、次のようなプログラムを考えます。
1: class NameTag1 { 2: public static void main (String[] args) { 3: System.out.println("------------------------------"); 4: System.out.println("------------------------------"); 5: System.out.println("NAME"); 6: System.out.println("------------------------------"); 7: System.out.println("AFFILIATION"); 8: System.out.println(); 9: System.out.println("------------------------------"); 10: System.out.println("------------------------------"); 11: } 12: }
b00a001@Ampere:~/java% java NameTag1 ------------------------------ ------------------------------ NAME ------------------------------ AFFILIATION ------------------------------ ------------------------------ b00a001@Ampere:~/java%
3行目、4行目、6行目などに、罫線を出力するという、まったく同じ処理が繰り返されています。 これらの処理に名前をつけ、その名前で処理が表せると、プログラムが書きやすくなります。 メソッド(method)というものを用いますと、そのようなことができます。 なお、メソッドにはインスタンスメソッド(instance method)とクラスメソッド(class method)があります。 今日はクラスメソッドのみ扱います。
メソッドとは、処理のまとまりに名前をつけたものです。 メソッドを使うためには、プログラムの中でメソッドを定義しなくてはいけません。 メソッドの定義は次のような形をとります。
static void methodname () { statement; ... }
これによって、処理のまとまり statement;
... に methodname という名前がつきます。
定義したメソッドを使うには、プログラムに次のような文を書きます。 これをメソッド呼び出し(method call)とよびます。
methodname();
プログラムの中にメソッド呼び出しがありますと、実行の流れは次の図のようになります。
メソッド呼び出し f();
を実行するとき、メソッド f
の定義の内容を実行し、それが終わったら、メソッド呼び出しの次から実行します。
上記のプログラムの場合、次のようになります。
罫線を出力するという処理に、rule
という名前をつけています。
メソッド呼び出し rule();
を実行しますと、罫線が出力されます。
1: class NameTag2 { 2: public static void main (String[] args) { 3: rule(); 4: rule(); 5: System.out.println("NAME"); 6: rule(); 7: System.out.println("AFFILIATION"); 8: System.out.println(); 9: rule(); 10: rule(); 11: } 12: static void rule () { 13: System.out.println("------------------------------"); 14: } 15: }
メソッド定義の中では、他のメソッドを使うこともできます。
次の例では、罫線を出力するメソッド rule
を使って、二重の罫線を出力するメソッド doubleRule
を定義しています。
1: class NameTag3 { 2: public static void main (String[] args) { 3: doubleRule(); 4: System.out.println("NAME"); 5: rule(); 6: System.out.println("AFFILIATION"); 7: System.out.println(); 8: doubleRule(); 9: } 10: static void rule () { 11: System.out.println("------------------------------"); 12: } 13: static void doubleRule () { 14: rule(); 15: rule(); 16: } 17: }
メソッドには引数(argument)を与えることができます。 引数とは、メソッドに対する入力データだと思ってください。 なお、引数はパラメタ(parameter)ともよばれます。
引数を持つメソッドは次のように定義されます。 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 { 2: public static void main (String[] args) { 3: multiRule(2); 4: System.out.println("NAME"); 5: multiRule(1); 6: System.out.println("AFFILIATION"); 7: System.out.println(); 8: multiRule(2); 9: } 10: static void multiRule (int n) { 11: int i; 12: for (i = 0; i < n; i++) { 13: System.out.println("------------------------------"); 14: } 15: } 16: }
メソッドは、まとまった処理をするだけでなく、何らかの計算をして、その値を呼び出し側に返すこともできます。 そのような値を、メソッドの返り値(return value)とよびます。 返り値は、メソッドの出力データと考えてください。
整数(int
型)を返り値に持つメソッドは、次のように定義されます。
static int methodname (int argument, ...) { statement; ... }
これまでの、返り値を持たないメソッド定義での void
の代わりに、int
と書きます。
この定義の中に、少なくとも一つ return
文を書きます。
return
文は次のような形をとり、式 expression の値がこのメソッドの返り値になります。
return expression;
返り値を持つメソッドは、次のような式で呼び出します。
methodname(argument, ...)
式の中にメソッド呼び出しがありますと、メソッド定義の内容が実行されます。
そして、その中の return
文が実行されますと、メソッドの実行は終了され、return
文の式の値が呼び出し側に返されます。
次の例では、二つの数のうち大きい方を返すメソッド max
を定義しています。
返り値を持つメソッドは、式として呼び出されることに注意してください。
1: class MaxTest { 2: public static void main (String[] args) { 3: System.out.println(max(100, 200)); 4: System.out.println(100 + max(20 + 30, 30)); 5: } 6: static int max (int m, int n) { 7: if (m > n) { 8: return m; 9: } else { 10: return n; 11: } 12: } 13: }
b00a001@Ampere:~/java% java MaxTest 200 150 b00a001@Ampere:~/java%
注意:
返り値を持たないメソッドでも return
文が使えます。
この場合、式を抜いた return;
という形になります。
メソッドの実行中に return
文を実行しますと、そこでメソッドの実行を終了します。
メソッドを呼び出すとき、仮引数には実引数の値が代入されます。 詳しく言いますと、呼び出しの際、仮引数の変数が用意され、そこに実引数の値のコピーが格納されます。 このような呼び出し方を、値呼び出し(call by value)とよびます。
次のプログラムは、引数を0にしようとしてもうまくいかない例です。
1: class BindingTest { 2: public static void main (String[] args) { 3: int x = 100; 4: zero(x); 5: System.out.println(x); 6: } 7: static void zero (int n) { 8: n = 0; 9: } 10: }
b00a001@Ampere:~/java% java BindingTest 100 b00a001@Ampere:~/java%
4行目のメソッド呼び出し zero(x);
を実行しますと、メソッド定義の7行目の変数 n
にデータ100のコピーが格納されます。
コピーを0に置き換えてメソッドを終了しますので、5行目の変数 x
の値は100のままなのです。
メソッドの例として、階乗を計算するメソッド fact
を定義して、いくつかの階乗を計算します。
ここで n の階乗とは、n ! と表され、
(7.1) n ! = 1×2×…×(n - 1)×n
と定義されるものです。 (n≧0 と仮定しています。)
1: class FactTest { 2: public static void main (String[] args) { 3: System.out.println("fact(4) is " + fact(4)); 4: System.out.println("fact(5) is " + fact(5)); 5: System.out.println("fact(6) is " + fact(6)); 6: } 7: static int fact (int n) { 8: int i, result = 1; 9: for (i = 1; i <= n; i++) { 10: result = result * i; 11: } 12: return result; 13: } 14: }
b00a001@Ampere:~/java% java FactTest fact(4) is 24 fact(5) is 120 fact(6) is 720 b00a001@Ampere:~/java%
順列とは、n 個の中から r 個並べる場合の数のことです。 これは n P r と表され、
(7.2) n P r = n×(n - 1)×…×(n - r + 1)
と計算できます。 また、次のようにも計算できます。
(7.3) n P r = n ! / (n - r) !
式 (7.2) にしたがって順列を計算するメソッド perm2
と、式 (7.3) にしたがって順列を計算するメソッド perm3
を定義し、以下のようにいくつかの順列を計算するプログラムを作成してください。
(上記の fact
メソッドを用います。
また、n≧r≧0 と仮定してください。)
b00a001@Ampere:~/java% java PermTest perm2(5, 2) is 20 perm3(5, 2) is 20 perm2(6, 4) is 360 perm3(6, 4) is 360 b00a001@Ampere:~/java%
今日の演習7にしたがってJavaプログラムを作成し、konishi@twcu.ac.jpあてにメールでそのプログラムを提出してください。 メールには、学生番号、氏名、科目名、授業の日付けを明記してください。