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

情報処理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.pow や Math.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.