メソッドは直訳すれば「方法」ですが、プログラム言語では一連の処理をまとめたものをメソッドと言います。
メソッドはいくつかの入力(無いときもある)を受け取り1または0個の値を出力します。入力する値たちのことを引数(ひきすう)といい、出力する値のことを戻り値と言います。

メソッドの例

ここではまず、簡単なメソッドの例を示しましょう。 以下は2つの数を受けとって、その和を返すメソッドです。 先頭のintは戻り値の型です。 このメソッドの結果をint型で返すことを示しています。 次のaddがこのメソッドの名前で、その次の丸括弧 ( ) の中が引数です。 引数はデータ型と引数名とをペアにして書きます。 複数ある時はコンマで区切ります。 次の波括弧 { 以降に処理の中味を記述します。 returnはこのメソッドが返す値を指定するものです。 最後の波括弧 } でメソッドを終わります。

			int add (int n1, int n2) {
				int sum;
				sum = n1 + n2;
				return sum;
			}
		

メソッドの呼び出し方

Javaでは メソッドの名前を書くと、そのメソッドが実行されます。 戻り値を返す時は、以下のようにメソッド自身を変数に代入する形で使用されます。 メソッドはこのような形式で使われるので関数と呼ばれることもあります。

			c = add(a, b);

		

※ メソッドの定義では引数にデータ型と引数名とをペアで書きますが、呼び出すときは単に引数名だけを書きます。 初めのうちは混同しやすいので、よく覚えてください。

メソッドの構成

     修飾子 戻り値の型 メソッド名(引数のリスト){
       メソッド本体
     }

メソッドの一般形は上のようになります。 それぞれの項目について、簡単に説明します。 上の書式の1行目書式、すなわち修飾子から丸括弧の終わりまでを、そのメソッドのシグニチャーと呼んでいます。

修飾子

修飾子はメソッドに様々な属性を与えるもので、必要に応じて記述します。 修飾子はクラスにかかわるものが多いので、後のクラスの章で詳しく説明します。

戻り値の型

メソッドが処理結果として持って帰る値(戻り値)の型を記述します。 戻り値が無いときはvoid(ボイド)型としてその旨を表明します。 voidは英語で空(くう)のとか無効のとかいった意味です。 メソッドの本体では、voidの時を除き、ここで記述した型を持つデータをreturn文で返さなければなりません。

メソッド名

メソッド名には自由な名前をつけられます。 但し識別子ですので、使用する文字は1章で述べた命名規則に従う必要があります。

丸括弧 ( )

メソッド名の直後の丸括弧は引数がなくても、必ず書きます。 それによって変数かメソッドかの区別をしているからです。

引数のリスト

引数のリストは、データ型名と引数名とをペアで記述します。 引数が複数あるときはこのペアをコンマで区切って書きます。 メソッドを呼び出すときは引数のデータ型と数、および順序が一致していなければなりません。

確認問題 4.1

double型の値 a と b とを受け取り、a と b との積をdouble型で返すメソッド product を作ってください。


データの渡し方 ★

メソッドが呼ばれると引数の値が(コピーして)メソッドに渡されます。 次のプログラムを見てください。 a と b の値を入れ換えています

			void swap(int a, int b) {
				int work = a;
				a = b;
				b = work;
			}
		

しかしこのメソッドを swap(x,y) と呼んでも、x と y の値は入れ代わりません。 メソッドを呼ぶ時には x と y の値をコピーして渡しているだけなので、元の x と y には何の影響も及ぼさないからです。

このように入力パラメーターとして、値そのものを渡すやり方を「値渡し」と言います。 データの渡し方はこの他に、その格納アドレスを渡す「参照渡し」があります(参照とはアドレスのことです)。 Javaのメソッドはすべて「値渡し」になります。

参照型データの受渡し

先に配列のところでも述べたように、基本データ型以外の変数は参照型と言って、値ではなくその値の格納域のアドレスが入っています。 参照型データをメソッドに渡すと、このアドレスが「値渡し」されるので、事実上「参照渡し」になります。

配列を使うと次のように内容を交換するプログラムを記述することができます。

			void swap(int[] a) {     // a[0]とa[1]との値を交換する
				int work = a[0];
				a[0] = a[1];
				a[1] = work;
			}
		

これを呼ぶプログラムは以下の通りです。 これにより x[0] は 20、x[1] は 10 になります。

			int[] x = {10, 20};
			swap(x);
		

可変長引数

メソッドを宣言する時に以下のようにデータ型名の後ろに「...」と記述しておくことで、引数の数を可変にできます。

			void vari(String... parm){
		

呼び出す側では、以下のように引数の個数を自由に選べます。

			vari("a");
			vari("xxx", "yyy", "zzz");
		

可変長引数として宣言された変数は、実際に配列になります。 したがってメソッドの中で引数を使うときは次のように配列を使用します。

			viod vari(String... parm) {
				for(int i = 0; i < parm.length; i++) {
					System.out.println(parm[i]);
				}
			}
		

以下、可変長引数を使用するときの注意点を示します。

  • 引数のデータ型は共通でなければなりません。
  • 他に引数があるとき、可変長引数は最後の引数にしか適用できません。
  • 呼び出す時の引数の個数が0個でもかまいません。
  • 名前が同じで引数の個数が固定のメソッドと可変のメソッドが混在した場合(メソッドがオーバーロード[後述]されている場合)、引数の個数が固定のメソッドが優先されます。

確認問題 4.2

次のメソッドがあります。


     void change(int a, int[] b){
       a = 15;
       b[0] = 4;
     }

このメソッドを呼び出す次のプログラムを実行すると、a と b[0] の値はどうなりますか。

     int a =10;
     int[] b = {1, 2, 3};
     change(a, b);


mainメソッド

独立したJavaのアプリケーションプログラムはmainと言う名前のメソッドから実行を開始します。 mainメソッドのシグニチャは次の通りです。

			public static void main(String[] args)
		

public

どのプログラムからもアクセスできると言う意味です。 GLOBALの概念に似ています。 詳細はクラスの章で説明します。

static

通常のメソッドは(参照型なので)newしなければメモリ領域に展開されませんが、staticとすると、newしなくても展開されます。 mainメソッドは最初に実行されるので、誰もnewしてくれず、staticにしておく必要があるのです。 詳細はクラスの章で説明します。

void

戻り値が無いことを示します。 mainメソッドでは値を返しても誰も受け取ってくれないので、必ずvoidにします。

main

これはメソッドの名前です。 必ずmainにします。

String[ ]

OSからJavaアプリケーションを起動するときに指定したパラメーターを、引数として受け取ります。 その引数が文字列の配列であることを示しています。

args

引数の変数名です。 変数名ですから何と書いても良いのですが、このように書くのが慣例です。 argumentsの略です(多分)。 読み方はよくわかりませんが、私(筆者)は「アーギュス」と発音しています。

確認問題 4.3

mainメソッドのシグニチャを何も見ずに書いてください。 それぞれの語の意味を言ってください。


コマンドライン

WindowsなどのOSからJavaアプリケーションを起動するときの、一連の命令(コマンド)の書式をコマンドラインと言います。 コマンドラインの例を示します。

			java Sample apple banana    // ☆
		

上記でjavaはjavaを実行させるコマンド、Sampleがプログラム名、appleとbananaがパラメーターです。 これらを受け取って、プログラムで使うときの変数がargsなのです。 以下にargsの使用例を示します。

			class Sample {
				public static void main(String[] args) {
					System.out.println("最初の引数は " + args[0] + " です");
					System.out.println("2番目の引数は " + args[1] + " です");
				}
			}
		

★ このプログラムは上述のコマンド☆に対し次のように出力します。

			最初の引数は apple です
			2番目の引数は banana です
		

※ このプログラムはこのままでは問題があります。 それは実行時に ☆ のようにパラメーターを必ず入力するとは限らないからです。
ユーザーがパラメーター無しで単に「java Sample」のように入力してしまうと、args[0] は定義されないので未定義の配列をアクセスすることになり、例外が発生してしまいます。 これを避けるには args[0] を呼ぶ前に、args.length(args配列の長さ)を調べて、想定値と異なるときはその旨を出力して、再入力を促す必要があります。 例えばパラメーターを1つだけ要求する場合は次のようにします。

			if ( args.length < 1 ) {
				System.out.println ("xxを入力してください。");
				exit(1);
			}
		

※ C言語では args[0] にはプログラム名が入っていて、args[1] に最初の引数が入っています。 しかしJavaでは最初の引数を args[0] で取得しますので、Cプログラマーは注意が必要です。

変数のスコープと初期化

メソッドの中で一時的に使用する変数を宣言することができます。 「データの渡し方」の項のプログラム例で使ったworkなどがその例です。 これらはメソッド内部のみで有効であり、ローカル変数と言います。 ローカル変数は他のメソッドで宣言された同名のローカル変数と衝突しません。

変数のスコープ

ローカル変数という考え方はメソッドに限らず、ブロック(波括弧 { } でくくられた範囲)について有効です。 以前for文のところ(for文内での変数の型宣言)で説明しましたが、for文の有効範囲も波括弧 { } で囲まれているのでブロックです。 このような変数の有効範囲を変数のスコープと言います。

初期化のデフォルト設定 ★

メソッドの外で宣言された基本データ型の変数は、デフォルト値(1章の基本データ型の項参照)で初期化されますが、メソッドの中で宣言された変数は値が入っていないので、初期化せずに使うとコンパイルエラーになります。

確認問題 4.4

次のプログラムをコンパイルして実行しようとするとどうなりますか。


     class Sample {
       public static void main(String[] args) {
         int a = 1;
         m1();
       }
       static void m1() {
         System.out.print(a);
       }
     }


オーバーロード

Javaは引数の数と型が異なれば、同名のメソッドを複数定義することができます。 これをメソッドのオーバーロードと言います。 オーバーロードの機能が無いと処理する引数の型の違いなどにより、類似した名前のメソッドを作る必要があります。
例えばC言語では、標準ライブラリとして提供されている、絶対値を計算する関数には次の3種があります。

			abs();   int型のデータの絶対値を返す
			fabs();  double型のデータの絶対値を返す
			labs();  long型のデータの絶対値を返す
		

ところがJavaでは、オーバーロードの機能により、int型、long型、float型、double型のデータの絶対値を計算する4種類のメソッドがすべてabsという1つの名前ですみます。 引数として与えるデータの型によってコンパイラが選択するからです。

★ オーバーロードをコンパイラが識別するには、引数の数と型と順序のいずれかが異なっている必要があります。 戻り値の型が異なるだけでは識別できません。 以下の3つのメソッドは同一クラス内では、どの2つをとっても同時には定義できません(コンパイルエラーになります)。

			String method(int x, String str)
			String method(int x, String xyz)
			int method(int x, String str)
		

確認問題 4.5

次のプログラムのうちオーバーロードの関係にあるものを全部挙げてください。


  01: void meth(int a); int meth();
  02: int meth(int a); void meth(int b);
  03: int meth(int x); int meth(int a);
  04: int meth(int a, String s); int meth(String s, int a);

ページの先頭へ