前回に引き続き、メソッドを作成し、それを利用する方法を確認しましょう。
前回の記事はこちら。
戻り値のあるメソッド
戻り値とは、処理の結果を返すためのものです。
メソッドによっては、処理そのものが重視されるタイプのメソッド(System.out.println( )などは画面への文字出力が重視され、戻り値は重要ではない)もありますが、例えば、演算をしてその結果を返すのが重要なメソッドもあります。
そういった場合に戻り値が必要となります。
戻り値を返すメソッドは以下のように記述します。
[static] 戻り値の型 メソッド名(引数リスト){ メソッドの中身; retrun 戻り値のデータ; }
実際に戻り値として返す値は、「return文」で指定します。
戻り値のデータには、変数または定数を記述できます。
但し、戻り値のデータ型は、メソッドの戻り値の宣言をした型と一致していなくてはなりません。
例えば、以下のようなメソッドが宣言されていた場合、このメソッドの内部でreturnできるのはint型のみとなります。
static int max(int num1, int num2){ }
例えば、上記のメソッドmaxがint型の戻り値を返すとしましょう。
すると、メソッドの全体は以下のようになります。
return
戻り値を返す必要のないメソッドであれば戻り値をvoid と指定します。
また、戻り値がvoidであれば、returnを省略することもできます。
戻り値は必ずメソッドの宣言で指定した型と合致するデータを指定してください。
return文はメソッドを終了し、戻り値として指定された値を返します。
return 文を用いる場所
return文はメソッドを終了し、戻り値として指定された値を返す意味があります。
ですから、return文の後にはどのような処理も来ないはずです。
そこで、Javaではreturn文の後に処理が続く場合、これをコンパイルエラーとしてしまいます。
そのため基本的にはreturn文はブロックの1番最後に来ます。
【戻り値を持つメソッド】
public class ReturnValue{ public static void main(String[ ] args){ int ret, data = 10; ret = max(data, 30); System.out.println("戻り値は : " + ret); } // メソッドの定義 static int max(int num1, int num2){ if(num1 > num2){ return num1; } return num2; } }
実行結果
戻り値は : 30
メソッドの呼び出しは4行目で行っています。
ここではmaxという名前のメソッドにint型の変数dataと整数の30を渡して、その2つの値を比較した結果をint型の変数retに代入しています。
メソッドの処理としてはif文による値の大小を比較しているだけのものです。
そして大きい方の値を返すようにしています。
結果を戻り値として返している部分が10行目と12行目になります。今回はint型を返すメソッドとして作成しています。
num1またはnum2はint型ですので問題なく値を返せます。
メソッドのオーバーロード
メソッドの「オーバーロード」とは、複数のメソッドに同一の名前をつけることです。
例えば、int型の2つの値を比較して大きい方の値を返す、メソッドを作成したとします。
作成してみると次のようになるはずです。
static int max(int a, int b){ if(a > b){ return a; } return b; }
ところで、このmaxメソッドは引数や戻り値がint型です。
もし、double型を用いた同様の処理を行うメソッドが欲しくなったらどうでしょうか?
当然、現状ではint型のmax( )メソッドしかありませんので、double型のmax( )メソッドを作ることになります。
static double max(double num1 , double num2){ if(num1 > num2){ return num1; } return num2; }
このように、同一メソッド名で、引数の型が違うメソッドを作成しました。
これが、「オーバーロード」です。
オーバーロードが成立する条件
オーバーロードをするためには、オーバーロードするメソッド間で、次のいずれかを満たしている必要があります。
もし満たしていなければ、コンパイルエラーとなりますので注意してください。
- 引数の数が違う
- 引数の型が違う
- 引数の並びが違う(データ型の並び)
メソッドの区別の方法
Javaではメソッドの区別はメソッドの名称及び引数リストで行い、この2つを合わせて、メソッドの「シグネチャ」と呼びます。
戻り値の型だけが違う場合は同じメソッドが複数あることになり、コンパイルエラーになりますので注意してください。
【オーバーロード】
public class ReturnValue2{ public static void main(String[ ] args){ int ret, data = 10; ret = max(data, 30); System.out.println("戻り値は : " + ret); double result, value = 12.3; result = max(value, 98.7); System.out.println("戻り値は : " + result); } // int型メソッドの定義 static int max(int num1, int num2){ if(num1 > num2){ return num1; } return num2; } // double型メソッドの定義 static double max(double num1, double num2){ if(num1 > num2){ return num1; } return num2; } }
実行結果
戻り値は : 30 戻り値は : 98.7
このプログラムで注意する部分は11行目と18行目で、同じ名前のメソッドを2つ定義していることです。
この2つのメソッドを次のように呼び出しています。
int ret, data = 10; ret = max(data, 30); System.out.println("戻り値は : " + ret);
double result, value = 12.3; result = max(value, 98.7); System.out.println("戻り値は : " + result);
ここで2つあるメソッドmaxの区別は引数の型で行っています。
4行目は、「引数がint型とint型の並びになっているmax( )メソッド」であり、
7行目は、「引数がdouble型とdouble型の並びになっているmax( )メソッド」を呼び出しています。
ポイント!オーバーロードされたメソッドの呼び分け
オーバーロードされたメソッドは、呼び出し側の引数として、どういうデータ型が渡されているのかで判断しています。
【メソッドの作成と呼び出し】
public class MethodYobidashi{ public static void main(String[ ] args){ // 戻り値、引数リストのあるメソッドの呼び出し String returnString = mojiretuRenketu("Hello, Java.", 3); System.out.println("mojiretuRenketuの結果 : " + returnString); // 引数があり、戻り値のないメソッドの呼び出し printMessage("こんにちは、Javaの勉強は進んでいますか?"); // 引数がなく、戻り値があるメソッドの呼び出し int returnVal = getCount( ); System.out.println("getCountの結果" + returnVal); // 引数も戻り値もないメソッドの呼び出し printHello( ); } static String mojiretuRenketu(String str, int i){ String ret = ""; for(int j = 0; j < i; j++){ ret += str; } return ret; } static void printMessage(String str){ System.out.println("メッセージは「" + str + "」です"); } static int getCount( ){ int i = 0; for(int j = 0; j < 10; j++){ i += j; } return i; } static void printHello( ){ System.out.println("Hello"); } }
実行結果
mojiretuRenketuの結果 : Hello, Java.Hello, Java.Hello, Java. メッセージは「こんにちは、Javaの勉強は進んでいますか?」です getCountの結果45 Hello
【同じメソッドの繰り返し呼び出し】
public class Sigma{ public static void main(String[ ] args){ int a = executeCalcSigma(10); // メソッドを呼び出し System.out.println("a = " + a); int b = executeCalcSigma(20); // 別の引数でメソッドを呼び出し System.out.println("b = " + b); int c = executeCalcSigma(30); System.out.println("c = " + c); int d = a + b + c; System.out.println("a + b + c = " + d); } // メソッドの定義 static int executeCalcSigma(int i){ int ans = 0; for(int j = i; j != 0; j--){ ans += j; } return ans; } }
実行結果
a = 55 b = 210 c = 465 a + b + c = 730
メソッドexecuteCalcSigmaをfor文の中から繰り返し実行するように変更します。
public class Sigma2{ public static void main(String[ ] args){ for( int i = 1; i < 20; i++ ){ int ans = executeCalcSigma(i); System.out.println(ans); } } // メソッドの定義 static int executeCalcSigma(int i){ int ans = 0; for(int j = i; j != 0; j--){ ans += j; } return ans; } }
実行結果
1 3 6 10 15 21 28 36 45 55 66 78 91 105 120 136 153 171 190
可変長引数
通常、メソッドを定義する際、引数のデータ型と数を決めておいて、呼び出しの際には、そのデータ型と数を定義に合わせて指定して、メソッドを呼び出します。
可変長引数を使用すると、メソッドの引数の数をあらかじめ決めておかないで、呼び出しのときに決めることができます。
上の例のように、メソッドがオーバーロードされている場合、該当のメソッドを呼び出すには、メソッドで定義されている引数のデータ型と引数の数に合わせて実引数を指定して呼び出す必要があります。
可変長で引数を指定しておくと、1つの引数定義で、複数の呼び出しに対応することができます。
【可変長引数の書式1】
メソッド名(可変長引数の型... 変数名){処理} (例)void main(String... args)
可変長引数の書式はデータ型の後にドットを3つ付け、変数名を指定します。
【可変長引数 書式1】
public class VariableArgs { public static void main(String[] args) { System.out.println("一回目:引数1つで呼ぶ"); variableArgs("A"); System.out.println("二回目:引数2つで呼ぶ"); variableArgs("A","B"); System.out.println("三回目:引数3つで呼ぶ"); variableArgs("A","B","C"); } //可変長引数をもつメソッドの定義 public static void variableArgs(String... str) { for(String s : str) { System.out.println(s); } } }
実行結果
一回目:引数1つで呼ぶ A 二回目:引数2つで呼ぶ A B 三回目:引数3つで呼ぶ A B C
このプログラムでは11行目から15行目でvariableArgsメソッドを定義しています。
このメソッドの引数は、String型の可変長引数が定義されています。
12行目から14行目の処理の内容は、可変長引数strに格納された複数のデータを、拡張for文を使用して、1つずつString型の変数sに代入しては、出力をします。
4行目ではこのvariableArgsメソッドを、引数を1つだけ指定して呼び出しています。
6行目ではこのvariableArgsメソッドを、引数を2つ指定して呼び出しています。
8行目ではこのvariableArgsメソッドを、引数を3つ指定して呼び出しています。
このようにvariableArgsメソッドの引数定義に可変長引数を指定すると、実際にメソッドを呼び出す際に、複数の実引数に対応することができます。
【可変長引数の書式2】
メソッド名(引数の型 変数名, 可変長引数の型... 変数名){処理} (例)void foo(int age, double height, String... args)
可変長引数は、可変長引数でない引数と同時に指定することが可能です。
その場合、可変長引数はその他の引数の定義よりも一番後ろに定義する必要があります。
void var(String s, int... x){ } → OK
void var(int... x, String s){ } → コンパイルエラー
また可変長引数を同時に複数指定することもできません。
void var(int... x, String... s){ } → コンパイルエラー
引数を明確に定義したメソッドと、可変長引数を使用したメソッドがオーバーロードされている場合は、引数を明確に定義したメソッドが優先して、呼び出されます。
void var(int... x){ }
void var(int x, int y){ } → 優先して呼び出される
【可変長引数 書式2】
public class VariableArgs2 { public static void main(String[] args) { variableArgs(1, "Apple"); System.out.println(); variableArgs(2, "Apple","Banana"); System.out.println(); variableArgs(3, "Apple","Banana","Orange"); System.out.println(); } //可変長引数をもつメソッドの定義 //public static void variableArgs(String... str, int age) {} //コンパイルエラー public static void variableArgs(int num, String... str){ System.out.println("Stringの引数の数:" + num + "個" ); for(String s : str){ System.out.println(s); } } }
実行結果
Stringの引数の数:1個 Apple Stringの引数の数:2個 Apple Banana Stringの引数の数:3個 Apple Banana Orange
11行目のvariableArgsメソッドでは、可変長引数の定義が、可変長引数でない引数の前に定義されているため、コンパイルエラーとなります。
可変長引数は必ず引数の定義の中で、1番最後に指定しなくてはなりません。
12行目から17行目のvariableArgsメソッドでは、int型の引数とString型の可変長引数の2つの引数を定義しています。
処理の内容は、int型引数numに渡された数値を使って、「Stringの引数の数」を出力したあと、拡張for文を使って、String型の可変長引数に渡されてきたデータを、実際に指定されたデータの数分取り出して、表示します。
3行目では、1つのint型の引数と、String型の引数1個指定して、variableArgsメソッドを呼び出しています。
呼び出された11行目のvariableArgsメソッドは、int型のデータ「1」を変数numに格納し、String型のデータ「Apple」を可変長引数の変数strに格納します。
5行目、7行目も同様に、String型の引数をそれぞれ2個および3個指定して、variableArgsメソッドの可変長引数strに渡しています。
【明確に引数を指定した場合と可変長引数を指定した場合】
public class VariableArgs3 { public static void main(String[] args) { variableArgs(1, "Apple"); } //可変長引数をもつメソッドの定義 public static void variableArgs(int num, String... str){ System.out.println("Stringの引数の数:" + num + "個" ); for(String s : str){ System.out.println(s); } } //明確に引数を指定したメソッドの定義 public static void variableArgs(int num, String str){ System.out.println("引数を明確に定義したメソッドがよびだされました"); } }
実行結果
引数を明確に定義したメソッドがよびだされました
6行目から11行目のvariableArgsメソッドでは、引数の定義に可変長引数を使用しています。
13行目から14行目のvariableArgsメソッドでは、引数の定義に可変長引数を使用せずに、int型とString型の引数を1つずつ定義しています。
3行目のようにString型の引数を1つ指定してvariableArgsメソッドを呼び出すと、13行目のString型の引数が1つだけ明確に定義されているメソッドの方が、優先して呼び出されます。
まとめ
- 戻り値のあるメソッド
処理の結果を返す場合は、戻り値を利用します。
戻り値を返す場合は、return文を利用します。
- メソッドのオーバーロード
複数のメソッドに同一の名前を付けることを、メソッドのオーバーロードと言います。
- 可変長引数
メソッドの引数に可変長引数を指定すると、複数の実引数を、1つのメソッドで実行することができます。
独学で挫折しそうになったら、オンラインプログラミングスクール