[小西ホームページ]   [目次・索引]   [前の授業]   [次の授業]

情報処理IIIA(Javaプログラミング入門)第7回

目次 索引
7.1 データ型
7.2 手続きとしてのメソッド
7.2.1 メソッドとは
7.2.2 メソッドの引数
7.3 関数としてのメソッド
7.3.1 メソッドの返り値
7.3.2 メソッドの例
7.4 演習7
7.5 レポート課題

7.1 データ型

データ型data type )とは、データの種類のことです。 これまでに、整数と配列の2種類のデータ型を扱ってきました。 Java言語には、この他のデータ型も用意されています。

Java言語のデータ型は、まず 基本型primitive type )と 参照型reference type )の2つに大きく分類されます。 基本型には、整数型、浮動小数点数型、論理型、および文字型があります。 参照型には、クラス型と配列型があります。 以下は基本データ型の詳細です。

表 7.1  Java言語の基本データ型
種類 型名 説明
整数型 byte -27(-128)〜27- 1(127)
整数型 short -215(-32768)〜215- 1(32767)
整数型 int -231(9桁程度)〜231- 1(9桁程度)
整数型 long -263(18桁程度)〜263- 1(18行程度)
浮動小数点数型 float 指数+38〜-45, 有効桁数7桁程度
浮動小数点数型 double 指数+308〜-324, 有効桁数14桁程度
論理型 boolean trueまたはfalse
文字型 char \u0000(0)〜\uFFFF(65535)

整数を扱う場合、普通は int 型を用います。 int 型の範囲を超えるような大きい数を扱うときに、 long 型を用います。 浮動小数点数を扱う場合、普通は double 型を用います。


7.2 手続きとしてのメソッド

7.2.1 メソッドとは

今、次のようなプログラムを考えます。

/* 1*/ class NameTag1 {
/* 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*/ }
b00a001@Ampere:~/java% java NameTag1
-------------------------
-------------------------
No.
-------------------------
Name

-------------------------
-------------------------
b00a001@Ampere:~/java%

3行目、4行目、6行目などに、罫線を出力するという、まったく同じ処理が繰り返されています。 これらの処理に名前をつけ、その名前で処理が表せますと、プログラムが読みやすく、かつ書きやすくなります。 メソッドmethod )というものを用いますと、そのようなことができます。 なお、メソッドには インスタンスメソッドinstance method )と クラスメソッドclass method )があります。 今日はクラスメソッドのみ扱います。

メソッドとは、処理のまとまりに名前をつけたものです。 メソッドを使うためには、プログラムの中でメソッドを定義しなくてはいけません。 メソッドの定義は次のような形をとります。

static void methodname () {
    statement; ...
}

これによって、処理のまとまり statement ; ...methodname という名前がつきます。

定義したメソッドを使うには、プログラムに次のような文を書きます。 これを メソッド呼び出しmethod call )とよびます。

methodname();

プログラムの中にメソッド呼び出しがありますと、実行の流れは次の図のようになります。 メソッド呼び出し f(); を実行するとき、メソッド f の定義の内容を実行し、それが終わったら、メソッド呼び出しの次から実行します。

Execution flow on a method call
図 7.1  メソッド呼び出しにおける実行の流れ

上記のプログラムの場合、次のようになります。 罫線を出力するという処理に、 rule という名前をつけています。 メソッド呼び出し rule(); を実行しますと、罫線が出力されます。

/* 1*/ class NameTag2 {
/* 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 {
/* 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*/         rule();
/*15*/         rule();
/*16*/     }
/*17*/ }

7.2.2 メソッドの引数

メソッドには 引数argument )を与えることができます。 引数とは、メソッドに対する入力データだと思ってください。 なお、コマンドライン引数はJavaアプリケーションの引数で、アプレット・パラメタはJavaアプレットの引数です。

引数を持つメソッドは次のように定義されます。 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("No.");
/* 5*/         multiRule(1);
/* 6*/         System.out.println("Name");
/* 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*/ }

メソッドを呼び出すとき、仮引数には実引数の値が代入されます。 詳しく言いますと、呼び出しの際、仮引数の変数が用意され、そこに実引数の値のコピーが格納されます。 このような呼び出し方を、 値呼び出しcall by value )とよびます。

次のプログラムは、引数を0にしようとしてもうまくいかない例です。

/* 1*/ class BindingTest {
/* 2*/     public static void main (String[] args) {
/* 3*/         int x = 100;
/* 4*/         setZero(x);
/* 5*/         System.out.println(x);
/* 6*/     }
/* 7*/     static void setZero (int n) {
/* 8*/         n = 0;
/* 9*/     }
/*10*/ }
b00a001@Ampere:~/java% java BindingTest
100
b00a001@Ampere:~/java%

4行目のメソッド呼び出し setZero(x); を実行しますと、メソッド定義の7行目の変数 n にデータ100のコピーが格納されます。 コピーを0に置き換えてメソッドを終了しますので、5行目の変数 x の値は100のままなのです。


7.3 関数としてのメソッド

7.3.1 メソッドの返り値

メソッドは、まとまった処理をするだけでなく、何らかの計算をして、その値を呼び出し側に返すこともできます。 そのような値を、メソッドの 返り値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 文を実行しますと、そこでメソッドの実行を終了します。

7.3.2 メソッドの例

メソッドの例として、階乗を計算するメソッド fact を定義して、いくつかの階乗を計算します。 ここで n の階乗とは、 n ! と表され、

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%

7.4 演習7

コマンドライン引数を読みこみ、その数を3桁ごとにコンマで区切って出力するJavaアプリケーションを作成してください。

b00a001@Ampere:~/java% java PutCommas 1
1
b00a001@Ampere:~/java% java PutCommas 1234
1,234
b00a001@Ampere:~/java% java PutCommas 999999
999,999
b00a001@Ampere:~/java% java PutCommas 10000000
10,000,000

このプログラムの作成にはいくつかの方針が考えられます。 オリジナルなものが望ましいのですが、思いつかない人は以下を穴埋めしてください。

class PutCommas {
    public static void main (String[] args) {
        int i, number = Integer.parseInt(args[0]);
        for (i = figureLength(number) - 1; i >= 0; i--) {
            System.out.print(figureAt(number, i));
            if (i % 3 == 0 && i > 0) {
                System.out.print(",");
            }
        }
        System.out.println();
    }
    static int power10 (int n) {
        ??? // 10 の n 乗を返す。
        ??? // 10 を n 回掛けるとよい。
        ??? // 10 の 0 乗が 1 であることに注意。
    }
    static int figureAt (int n, int index) {
        ??? // 数 n の右から index 番目の数字を返す。
        ??? // 右端を 0 番目とする。
        ??? // n を 10 の index 乗で割り、
        ??? // それを 10 で割った余りになる。
    }
    static int figureLength (int n) {
        ??? // 数 n の桁数を返す。
        ??? // 10, 100, 1000, ... と順に比較し、はじめて
        ??? // n より大きくなる 10 の i 乗の i になる。
    }
}

なお、コマンドライン引数は1以上10億(10桁)以下の整数と仮定してください。 また、 Math.powMath.log を使ったり、 StringBuffer クラスを用いるのは反則とします。

余力のある人は、 long 型を用いて100京(19桁)までできるようにしてください。 なお、 Integer.parseInt(args[0]) の部分は Long.parseLong(args[0]) になります。 また、 long 型の式 expression の値を明示的に int 型にするには、 (int) ( expression ) と書いてください。


7.5 レポート課題

今日の演習7に従ってJavaプログラムを作成し、そのプログラムをkonishi@twcu.ac.jpあてにメールで提出してください。 メールには、学生番号、氏名、科目名、授業日(11/1)を明記してください。


[小西ホームページ]   [目次・索引]   [前の授業]   [次の授業]

2001年11月1日更新
konishi@twcu.ac.jp
Copyright (C) 2001 Zenjiro Konishi. All rights reserved.