メソッドとは
これまで「public static void main(String[] args)」という言葉を入力し、その{}の中で様々な処理を記入してきました。
この{}で囲われた処理全体のことをメソッドと呼びます。
メソッドとは、「特定のクラスやオブジェクトに所属するグループ」のことを言います。
Javaではたくさんのクラスを作成し、それらを連携させることでプログラム全体を動かしますが、プログラムを動かすためには、「どこから処理を始めるか」ということを決めておく必要があります。
Javaのプログラムは、原則として必ず以下の一文から処理が開始します。
public static void main(String[] args) { }
この部分をmainメソッドと呼びます。mainメソッドの「{」と「}」の間(ブロック)に書かれている指示(メソッド)を、1つ目から順にコンピュータは実行していきます。
現状、mainメソッドの中ですべての処理を記載していますが、
行数が少ない処理であればそのような処理を書くこと自体は間違いではありません。
しかし、現場で作成する多くのシステムはプログラムの行数が1000行や2万行や、かなりのボリュームでプログラムを記載しています。
すべての処理をmainメソッドに書いていくと、どこにどのような処理を書いたのか目星がつけられなくなり、
結果的に非常に読みにくいプログラムとなってしまいます。
ではどのようにして分かりやすく書くかというと、
その一つの方法としてメソッドを新たに作り、処理をより見やすくするというものがあります。
実際にプログラムを書いて試してみましょう。
「com.cmps」内に新規にパッケージを作成し、「method」としてください。
「method」パッケージ内に新規クラスを作成し、「Method」という名称にして以下のソースを記入してください。
package com.cmps.method;
public class Method {
public static void main(String[] args) {
//メインメソッドに記載する時はこの記載だけ
//helloメソッドを呼び出します。
hello();
//goodByeメソッドを呼び出します。
goodBye();
}
//mainメソッド{}より外側、Methodクラスの{}より内側にメソッドのタイトルを記載します。
//メソッドの宣言は以下のように宣言します。
public static void hello() {
System.out.println("挨拶メソッドを実行します。");
System.out.println("こんにちは");
System.out.println("挨拶メソッドを終了します。");
}
//mainメソッド{}より外側、Methodクラスの{}より内側にメソッドのタイトルを記載します。
//メソッドの宣言は以下のように宣言します。
public static void goodBye() {
System.out.println("さようならメソッドを実行します。");
System.out.println("さようなら");
System.out.println("さようならメソッドを終了します。");
}
}
今回の処理でmainメソッド配下に記載しているのはhello()とgoodBye()の二つだけです。
代わりにhello()とgoodBye()がどのような処理なのかをそれぞれ記載しています。
mainメソッド内のhello()に注目してください。
メソッドを定義するには以下の記載が必要です。
メソッド名() { 処理内容 }
メソッド名はhelloやgoodByeなどの処理する部品の名前だと思って下さい。
「 { } 」で囲われた範囲(上記でいうと{ 処理内容 }の部分)は基礎でも取り扱ったブロック(メソッドブロック)です。
作成したプログラムのmainメソッドを見てみましょう。
hello()と記載することで、下に書いたhello()のメソッドブロックが呼び出されて実行されていることが出力結果から確認できます。
同じようにgoodByeを呼び出すと、下に書いたgoodBye()のメソッドブロックが呼び出されて実行されていることが出力結果から確認できます。
このように処理を分割することでmainメソッドに記載されている量がかなり少なくなり、分かりやすい記載になったと思います。
処理を部品化することで処理の全体の流れを分かりやすく表現することができます。
メソッドの基本構文
メソッドの基本構文は以下の通りです。
書式:メソッドの定義
static ①修飾子 ②戻り値の型 ③メソッド名(④引数){
⑤処理
⑥return 文
}
書式:メソッドを呼び出す記述
(メソッドが呼び出すと、動作が実行される)
メソッド名(引数);
メソッドの定義の書式を説明します。
①static修飾子
static修飾子は、これから定義するメソッドを、どのような範囲・形態で利用できるか、ということを表します。
static修飾子を使用することで、特定のインスタンスに依存せずにクラス自体でアクセスできるメンバーを作成できます。
(インスタンスやクラスについては別の単元で詳しく説明します)
②戻り値の型 ⑥return文と戻り値
戻り値は、そのメソッドで処理をして得られる結果のことで、メソッドの呼び出し元の処理で利用されます。戻り値を持つメソッドの場合は、必ずreturn文であらかじめ宣言していた型(intやdoubleなど)の戻り値を返さなくてはなりません。1つの値、もしくは1つの変数のみを返すことができます。
戻り値を持たないメソッドの場合、voidと記述します。
③メソッド名
メソッド名は、メソッドにつけた名前です。メソッド名は小文字から始まり、2つ以上の単語を繋げた名前にしている場合は2つ目以降の単語の頭文字を大文字にする(キャメルケース)のが慣例となっています。
④引数
引数は、メソッドを呼び出す時にそのメソッドに渡す値です。メソッドが受け取った引数は、メソッド内の処理で利用されます。
メソッドの定義部分に記述する引数を仮引数と呼びます。メソッド名の後ろの括弧の中には、必要な引数の型と変数名を記述しなくてはなりません。引数を複数受け取るメソッドの場合は、カンマで区切ります。
仮引数はブロック内でのみ有効で、ブロック外で利用することはできません。
⑤処理
メソッドの処理内容を書きます。引数を設定したメソッドの場合は、それを利用して処理を行います。
メソッドに値を渡して処理をさせてみる
Methodクラスの中に以下のソースを記載してみましょう。
まずはメインメソッド内です。
メインメソッドではこの後記述する各メソッドを呼び出して、実行しています。
//足し算メソッドを呼び出します。()にはメソッドで定義した型のデータを入力します。
//今回は(int num,int fig)で指定されているので、int型データを2つ送ります。
addition(5, 3);
//引き算メソッドを呼び出します。
subtraction(10, -5);
//メソッドを呼び出す時に渡す引数を変数にしてもOKです。
int num = 3;
int fig = 15;
//掛け算メソッドを呼び出します。
multiplication(num, fig);
//配列の合計を出すメソッドを呼び出します。
int allIn[] = { 25, 74, 347, 83, 291, 362, 22, 19, 469, 2926, 721, 2723, 111, 387 };
sumArray(allIn);
次に処理を記述したメソッドを作っていきます。
//足し算をするメソッド
public static void addition(int num, int fig) {
int answer = num + fig;
System.out.println("足し算の結果は" + answer + "です!");
}
//引き算をするメソッド
public static void subtraction(int fig, int num) {
int answer = num - fig;
System.out.println("引き算の結果は" + answer + "です!");
}
//掛け算をするメソッド
public static void multiplication(int num, int fig) {
int answer = num * fig;
System.out.println("掛け算の結果は" + answer + "です!");
}
//配列の中身をまとめて合計を出力するメソッド
//メソッドに指定する引数はListやMap、配列やクラスを渡す事も可能
public static void sumArray(int[] arr) {
int sum = 0;
for (int a : arr) {
sum += a;
}
System.out.println("この配列の合計は" + sum + "です!");
}
作成したメソッドでは、メソッド名右側の()にどのデータを入力するのかを指定することができます。
このメソッドに渡す値のことを引数と呼びます。
例えば、足し算をするメソッドadditionでは、「int num」と「int fig」のデータ型を引数にしています。
言い換えると、足し算メソッドを使うときは整数の値を2つ送って実行しましょう、という意味になります。
メインメソッドの呼び出す側の処理で「addition(5,3);」と指定をしているので、numには5,figには3が入ります。
なお、値を渡す場合、左から値を入れていくという特徴があります。
次の引き算メソッドでは、「int num」と「int fig」が逆に配置されています。
メソッドを呼び出すときにはどっちから先に入れるのかを指定することはできないので、
今回は「subtraction(10,-5);」で呼び出して、「int fig」には10を、「int num」には-5を格納しています。
掛け算メソッドでは、メインメソッドで定義されたint num,int figの変数をメソッドに引数として送っています。
変数の名前が同じになっているように見えますが、この場合でも引き算の時と変わらず、左から値をそのまま取り込んでいきます。
データ型であれば他にも値を引数として指定することが可能です。
これまで学んでできた配列、List、Mapも渡すことが可能です。
フィールド、変数が扱える範囲について
変数は本来、同じ変数名を使ってはいけない、というルールがあります。
そのため、処理の中で同じ変数を使おうとすると「重複ローカル変数」エラーが出力されます。
しかし、先程の処理を見てみると、「int num」「int fig」は様々な場所で宣言されて使えています。
これはスコープと呼ばれる概念に則って変数の宣言をしているためです。
スコープとは、変数が扱える範囲のことを意味します。
プログラムを書く中で{}を使って処理を行っていましたが、{}の位置によって使用できる変数の範囲が決まってきます。
まずは以下のソースをMethodクラスの配下、メインメソッドの外(上)に記述してみてください。
public class Method {
// (1)
// Methodクラス配下に変数を配置
public static List<String> list = new ArrayList<String>();
次のソースをメインメソッド内に記述してください。
public static void main(String[] args) {
// (1)の{}の範囲に含まれているので変数listが使えます。
list.add("こんにちは");
System.out.println(list);
// (2)
// Methodクラスの{}内で、メインメソッドの内なので、2つの{}で囲割れている状態です。
// この変数はメインメソッド内でのみ使用可能です。
int sampleInt = 1;
int sampleInt2 = 2;
System.out.println(sampleInt + sampleInt2);
Sub();
Stay();
Test();
}
Methodクラス内に新たなメソッド「Sub」「Stay」を作成してください。
public static void Sub() {
// (1)
list.add("こんばんは");
System.out.println(list);
// (2)
// Methodクラス配下の{}内、更にmainメソッド内の{}で2つ囲われています。
// この変数はSubメソッドでのみ使うことができます。
int sampleInt = 1000;
int sampleInt2 = 2000;
System.out.println(sampleInt + sampleInt2);
}
public static void Stay() {
list.add("いただきます");
System.out.println(list);
}
変数の影響範囲(スコープ)を(1)や(2)と表示しています。
(1)は、最も外側の{ }内に入っているデータ変数、(2)は、一つ内側の{ }内に入っているデータ変数を意味します。
(1)にあるlist変数ですが、{ }の内側であればどのメソッド処理でも値を使うことが可能です。
この処理においては、メインメソッド、Subメソッド、Stayメソッドでlistを使用していますが、
いずれも(1)の{ }内であるため、問題なく処理する事が可能です。
次に(2)ですが、メインメソッドとSubメソッドの中に
int sampleInt
int sampleInt2
といった変数がありますが、この変数は二つ目の{ }の範囲が異なります。
{ }内側で値を使う都合上、メインメソッドに使われている「sampleInt,sampleInt2」とSubメソッドに使われている「sampleInt,sampleInt2」は別の変数として取り扱われます。
メインメソッド内で定義した変数の加算結果System.out.println(sampleInt + sampleInt2);は3が、
Subメソッド内で定義した変数の加算結果System.out.println(sampleInt + sampleInt2);は3000が出力されていることからもわかるかと思います。
最後にTestメソッドを作成し以下を記述しましょう。
public static void Test() {
// (2)
int a = 0;
if (a == 0) {
// (3)
int b = 0;
if (a == 0 && b == 0) {
// (4)
int c = 0;
if (a == 0 && b== 0 && c == 0) {
// (5)
int d = 0;
System.out.println(d);
}
}
}
}
スコープについては{ }の数だけ範囲を絞っていくことが可能になります。
{ }より内側であれば変数はずっと使えるので、この処理のように何重にも処理が重なったとしても問題なく変数として使えます。
ただし、最初に「a」のint型を宣言しているので、
int bやint cの場所に再度int aを宣言することはできません。
Testメソッドではif文を使って中の{ }を増やしていますが、宣言した値は{ }よりも内側であればどこでも使用できるため、この処理もちゃんと動きます。
メソッドから値をもらってくる
先程はメソッドの処理を呼び出して、メソッド先で処理を行っていましたが、処理した結果をもらうことも可能です。
メインメソッド内に以下を記述しましょう。
int dataA;
int dataB;
/ データ投入メソッド
dataA = putNumberA();
dataB = putNumberB();
// 取得した値を表示
System.out.println("dataA:" + dataA);
System.out.println("dataB:" + dataB);
// 文字を返り値として受け取る
String sampleString = putString();
System.out.println(sampleString);
int answer;
//パターン1 voidメソッド計算
calcA(dataA, dataB);
// パターン2
answer = calcB(dataA, dataB);
System.out.println(answer);
// パターン3
answer = calcC(dataA, dataB);
System.out.println(answer);
Methodクラス内に以下のメソッドを作成してください。
// 値を返却するメソッド
// 「void」と記載していた箇所をintにする
public static int putNumberA() {
return 10;
}
// 値を返却するメソッド
// 返却時に変数を指定すれば、変数に格納されているあ値を返却可能
public static int putNumberB() {
int number = 10;
return number;
}
// 文字列を返却するメソッド
// 「void」の箇所をStringにする
public static String putString() {
return "String型の文字列です。";
}
// パターン1、値を返却しない計算メソッドでもreturn
public static void calcA(int x, int y) {
System.out.println(x + y);
return;
}
// パターン2、計算結果を返却するメソッド
public static int calcB(int x, int y) {
int ans = x + y;
return ans;
}
// パターン3、計算結果の返却を簡略化
public static int calcC(int x, int y) {
return x + y;
}
以前、戻り値を持たないメソッドの場合はvoidと記述するとお伝えしましたが、この「void」の代わりにデータ型を入れると、値を取得することが可能になります。
メソッドを実行した時に取得できた値のことを戻り値(ないし返り値、返却値)と呼びます。
処理を順を追って見ていきましょう。
まず、変数dataAにputNumberA()メソッドを実行して戻り値をdataAに格納します。
putNumberAメソッドが呼ばれたことで、メソッドが実行されます。
このメソッドは「public static 【int】putNumberA」と記載があるため、
intのデータ型を返却するメソッドであることが分かります。
具体的な値を返却するときは「return」を使って値の返却を行います。
この処理ではreturnに10の値を指定しているため、putNumberAの戻り値は10になります。
なお、putNumberBメソッドのように戻り値に変数を記載する事も可能です。
putStringメソッドでは「void」の箇所が「String」となっているので、returnに文字列を与えて返却しています。
上述のintの返却を行った時と同じく、文字列を取得できていることを確認できます。
返却する型はListやMap、配列でも返却可能です。
後半のパターン1から3は、いずれも引数で受け取った値を使い足し算を行っています。
戻り値のいらないパターン1では「void」が指定されています。このメソッドでは変数=メソッド名()の書き方はできません。
しかし、voidを使った戻り値がない処理なのに「return;」が記載されています。
このreturnはメソッドの処理はここが最後ですと処理を打ち切るときに使うことがあります。
パターン2からは返却値があるため、値を取得できます。
なお、簡単な計算なのであれば、「return」の値を直接計算する書き方をしても問題ありません(パターン3)。
練習問題
「com.cmps.method」内に「MethodQuestion」クラスを作成し解きましょう。
(1)は変数の影響範囲(スコープ)を表します。
package com.cmps.method;
public class Question {
// (1) ←※スコープを意味します
//問題①int型の変数numとfigを宣言してください。
// ※「static」をつけて、クラス変数として作成しましょう。
// クラス変数とすることで、インスタンスを作らなくてもアクセス可能となります。
//問題②(1)のnumとfigに値を代入する「input」メソッドを作成してください。
// numには10を、figには5を代入してください。
//問題③calcメソッドを作成してください。
// calcメソッド内では、引数をint numeral、int digit、として指定を行い、
// 「2 * numeral+3 * digit」の計算結果を戻り値として返してください(returnする)。
public static void main(String[] args) {
//問題④inputメソッドとcalcメソッドを呼び出してください。
// calcメソッドは、(1)のnumとfigを引数に用いて処理を呼び出し、返された結果をSystem.out.println();で出力しましょう。
// 問題⑥int num,int figを使って問題⑤で作成するメソッドを呼び出し、
// 各メソッドの戻り値を 変数ansの中に格納し、ansを出力しましょう。
int num = 10;
int fig = 5;
int ans = 0;
// 足し算の結果を格納
System.out.println(ans);
// 引き算の結果を格納
System.out.println(ans);
// 掛け算の結果を格納
System.out.println(ans);
}
//問題⑤int num,int figの値を引数として取得し、
// 足し算、引き算、掛け算の結果を戻り値として返却するメソッドを作成してください。
// ただし、メソッドは3つ作り、1つのメソッドに対して1つの計算のみを記載してください。
}
結果としては、35、15、5、50が出力されていればOKです。
