JAVA　基本文法[6] - メソッド

##### 「メソッド」と「メソッドの定義/呼び出し」
●メソッド
とは、複数の文をまとめ、それを１つの処理として名前を付けたもので、部品の最小単位になる。長～いプログラムを複数の「部品」に分けて作ることが出来るしくみを備えている。

「メソッドを使ってプログラムを部品化することができる。」

メリット
・プログラムの見通しがよくなり、全体を把握しやすくなる。
・機能単位に記述するため、修正範囲を限定できる。
・同じ処理を１つのメソッドにまとめることで、作業効率が上がる。

メソッドを使用するには、まず「メソッドの定義（メソッドを作成）」をし、「メソッドを呼び出す（作成したメソッドを使用する）」。※セットで捉えるのではなく、２つの立場は切り分けて捉えること。

●メソッドの定義
クラスブロック内でメソッドの定義をする。

::: note alert
メソッドの定義
public static 戻り値の型 メソッド名(引数リスト) {
 メソッドが呼び出されたときに実行される具体的な処理
}
:::
<img width="300"
src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1162001/b2bb0c9a-a9bd-0401-967d-275820e19d4d.png">

```Main.java
//例）
public class Main {
  public static void hello() { //helloメソッドの定義
    System.out.println("マイク、こんにちは"); //メソッドが呼び出されたときに実行される具体的な処理
  }
}
```
メソッドの呼び出しがされていない為、上記のままではコンパイルは通っても実行はできない（処理は行われない）。

●メソッドの呼び出し
メソッドを使用することを「メソッドを呼び出す」という。
メソッドは定義しただけでは実行されず、呼び出すことで初めて、メソッドブロック内の処理が実行される。

::: note alert
メソッドの呼び出し
メソッド名（引数リスト）
※基本的に、「（引数リスト）」はそのまま「（）」と記載するケースが多い。
:::
mainメソッドより上に別のメソッドが定義されていても、「プログラムは必ずmainメソッドから動き始める！！」
各メソッドの動作する順序は、mainメソッドを起点にどう呼び出されていくかで決まる。

↓呼び出されたメソッドの処理が終了すると、メソッドの呼び出し元に戻って処理の続きが実行される↓
<img width="400"src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1162001/0c6c8322-f3f0-8f72-a924-6bd08c202fdd.png">
```Main.java
//メソッドの呼び出し
public class Main {
  public static void main(String[] args) { //mainメソッドはここから
    System.out.println("メソッドを呼び出します");
    hello();//helloメソッドを呼び出す
    System.out.println("メソッドの呼び出しが終わりました");
  }//mainメソッドはここまで
  public static void hello() { //helloメソッドの本体はここから
    System.out.println("湊さん、こんにちは");
  }//helloメソッドの本体はここまで
}
/*実行結果
メソッドを呼び出します
湊さん、こんにちは
メソッドの呼び出しが終わりました
*/
```
```Main.java
//例）mainメソッド以外からメソッドを呼び出す
public class Main {
  public static void methodA() {
    System.out.println("methodA");
    methodB();//methodBの呼び出し
  }
  public static void methodB() {
    System.out.println("methodB");
  }
  public static void main(String[] args) {
    methodA();//methodAの呼び出し
  }
}
/*実行結果
methodA
methodB
*/
```
---

###### 引数の利用
<img width="400"src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1162001/aa2afbb6-f820-0acc-b370-085828f5c27a.png">
「メソッドを呼び出す際」に、呼び出し元から値を渡すことが出来る。
この時に渡される値を「引数」という。呼び出されたメソッド側では、渡された値を受け取って処理に使用することが出来る。
※引数には数値や文字列などを指定でき、その値や型、渡す引数の数は開発者が自由に決められる※
「メソッドの呼び出し時に引数として値を渡すことが出来る」

渡す値、受け取る変数ともに「引数」と呼ばれるが、
渡す値を「実引数」。受け取る変数を「仮引数」という。
<img width="240"src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1162001/eedaba6e-d2d9-260d-8b70-9416c842f25b.png">

●１つの引数を渡す

::: note
１つの引数を利用する際の、メソッドの呼び出しと定義
★メソッドの定義
public static 戻り値の型 メソッド名(引数の型 変数名) {
 メソッドが呼び出されたときに実行される、「変数名を使った」具体的な処理
}
※メソッドが呼び出されると、「変数」に引数として渡された値が代入される。そして処理で使えるようになる。

★メソッドの呼び出し
メソッド名（引数リスト）
※()内に引数を入れる。
:::
```Main.java
//渡す値が１つの例
public class Main {
  public static void main(String[] args) {
    System.out.println("メソッドを呼び出します");
    hello("ダイゴ"); //"ダイゴ"を渡して、helloメソッドを呼び出す
    hello("ゆい");  //"ゆい"を渡して、helloメソッドを呼び出す
    hello("えみ");  //"えみ"を渡して、helloメソッドを呼び出す
    System.out.println("メソッドの呼び出しが終わりました");
  }
  public static void hello(String name) {
    System.out.println(name + "さん、こんにちは");
  }
}
/*実行結果
メソッドを呼び出します
ダイゴさん、こんにちは
ゆいさん、こんにちは
えみさん、こんにちは
メソッドの呼び出しが終わりました
*/
```

●複数の引数を渡す例
渡すほうも受け取るほうも、値を「カンマで区切って」使用する。
「引数として渡される値と、メソッド側で宣言する変数の型と順番を合わせる。」
引数と受け取る側の変数で型が異なる場合には代入出来ずエラーになるので注意。

::: note
複数の引数を利用する際の、メソッドの呼び出しと定義
★メソッドの定義
public static 戻り値の型 メソッド名(引数の型❶ 変数名❶, 引数の型❷ 変数名❷) {
 メソッドが呼び出されたときに実行される、「変数名を使った」具体的な処理
}
※メソッドが呼び出されると、「変数」に引数として渡された値が代入される。そして処理で使えるようになる。

★メソッドの呼び出し
メソッド名（引数リスト❶, 引数リスト❷）
※()内に引数を入れる。
:::
```Main.java
//例）　渡す値が複数の場合
public class Main {
  public static void main(String[] args) {
    add(100, 20, "です");
    add(200, 50, "です");
  }
  // 複数の値を受け取るaddメソッド
  public static void add(int x, int y, String z) {
    int ans = x + y;
    System.out.println(x + "+" + y + "=" + ans + z);
  }
}
/*実行結果
100+20=120です
200+50=250です
*/
```

::: note alert
引数の渡し方まとめ
・何も渡さない場合：メソッド名（）
・値を１つ渡す場合：メソッド名（値）　
・値を複数渡す場合：メソッド名（値,値,…）
※値には、変数名を指定することも出来る。
:::

●変数のスコープとローカル変数
・変数ではなく、引数を使用する訳とは、「変数のスコープ」が原因である。
ブロックの内で宣言された変数のスコープは、そのブロック内に限定される。

・メソッド内で宣言した変数を「ローカル変数」と呼ぶ。
ローカル変数は、その変数が属するメソッド内だけで有効な存在であって、「別のメソッドに属する同名のローカル変数とは全くの別物」である。
異なるメソッドに属するローカル変数は、お互いに独立していて無関係である。

---
##### 戻り値の利用
呼び出されたメソッドから、呼び出し元のメソッドへ値を返すことを「値を戻す（値を返す）」という。
また、戻される値のことを「戻り値（返り値）」という。
「戻り値は引数と違い、１つしか指定できない。」
<img width="500"src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1162001/dc8dcd7a-76d0-18b3-df76-c5af0ad5aea5.png">

●値の戻し方

::: note
値の戻し方（メソッドの定義）
public static 戻り値の型 メソッド名(引数リスト) {
 メソッドが実行された時に動く処理
　　return 戻り値;
}
:::

「return（return文）」の後ろに書かれた値を呼び出し元に戻すことができる。戻り値は、変数名でもリテラルを記述してもOK。
return文は値を戻すだけでなく、「メソッドの終了も行う」。その為、return文の後に処理を書いてもコンパイルエラーになり、実行されない。

「戻り値の型」は「returnによって戻される値と同じ型」を指定する。80のような整数の場合はint、"hello"のような文字列の場合はString、変数に入っている値を戻す場合はその変数の型を記述。
「何も戻さない場合」は、「void」を指定。


●（メソッドを呼び出し、）戻り値を受け取る方法

::: note
メソッドを呼び出し、戻り値を受け取る
型 変数名　= メソッド名（引数リスト）;
※「メソッド名（引数リスト）」はメソッドの呼び出しを意味する。
※右辺左辺を逆にしてしまうとコンパイルエラーになるので注意。
:::
・代入演算子「＝」がある為、右辺から先に評価れるということを忘れないようにしよう。
つまり、「メソッド名（引数リスト）」という部分を評価され、戻ってきた値「戻り値が変数に代入される」イメージ。
型 変数名　= メソッド名（引数リスト）
↓
型 変数名　= 戻り値
・必ず変数で受け取ること。

```Main.java
//戻り値の例
public class Main {
  public static int add(int x, int y) {
    int ans = x + y;
    return ans;
  }
  public static void main(String[] args) {
    int ans = add(100, 10); //addメソッドの呼び出し。後に110に化ける。
    System.out.println("100 + 10 = " + ans);
  }
}
/*実行結果
100 + 10 = 110
*/
```

---
###### オーバーロードの利用
プログラムが大きくなると、似たような処理を行うメソッドが複数あるというケースがある。しかし、このような場合でも「メソッドに同じ名前をつけることは基本的に出来ない」。
ただ、例外的に同じ名前のメソッドを定義することできる。
同じ名前のメソッドを定義することを「オーバーロード（多重定義）」という。

::: note
オーバーロードが可能なケースとは…
・引数の「型」が異なる場合
・引数の「数」が異なる場合
:::
```Main.java
//オーバーロードが可能な例：引数の型が異なる場合
public class Main {
  // 1つ目のaddメソッド
  public static int add(int x, int y) {
    return x + y;
  }
  // 2つ目のaddメソッド
  public static double add(double x, double y) {
    return x + y;
  }
  // 3つ目のaddメソッド
  public static String add(String x, String y) {
    return x + y;
  }
  public static void main(String[] args) {
    System.out.println(add(10, 20));// 1つ目のaddメソッドが呼び出される
    System.out.println(add(3.5, 2.7));// 2つ目のaddメソッドが呼び出される
    System.out.println(add("Hello", "World"));// 3つ目のaddメソッドが呼び出される
  }                    
}
/*実行結果
30
6.2
HelloWorld
*/
```
```Main.java
//オーバーロードが可能な例：引数の数が異なる場合
public class Main {
  public static int add(int x, int y) {
    return x + y;
  }
  public static int add(int x, int y, int z) {
    return x + y + z;
  }
  public static void main(String[] args){
    System.out.println("10+20=" + add(10, 20));
    System.out.println("10+20+30=" + add(10, 20, 30));
  }
}
/*実行結果
10+20=30
10+20+30=60
*/
```
---
##### 引数や戻り値に配列を用いる
●引数に配列を用いる
メソッドの引数には、変数だけでなく「配列」も扱える。
```Main.java
//引数に配列を受け取る
public class Main {
  // int型配列を受け取り、すべての要素を表示するメソッド
  public static void printArray(int[] array) { //引数に「配列型」を指定
    for (int element : array) {
      System.out.println(element);
    }
  }
  public static void main(String[] args) {
    int[] array = {1, 2, 3};
    printArray(array);    // 配列を渡す
  }
}
/*実行結果
1
2
3
*/
```
配列型の変数には、配列の実体を指し示すメモリの番地が格納されている。
従って、printArrayメソッドに引数として渡しているのは「配列丸ごと」ではなく、「アドレス情報」のみである。
配列を渡すあるいは戻すときは、配列そのものではなく配列のアドレスを渡している。これを「共有渡し」という。

●戻り値に配列を用いる
```Main.java
//戻り値が配列の場合
public class Main {
  public static int[] makeArray(int size) { //int型配列を作成して戻すメソッド
    int[] newArray = new int[size];
    for (int i = 0; i < newArray.length; i++ ) {
      newArray[i] = i;
    }
    return newArray; //配列を戻す
  }
  public static void main(String[] args) {
    int[] array = makeArray(3);
    for (int i : array) { //このfor文で、arrayの全要素を出力
      System.out.println(i);
    }
  }
}
/*実行結果
0
1
2
*/
```
---
##### コマンドライン引数
Javaのプログラムを起動する際、様々な「追加情報」を指定して起動することが出来る。このプログラム起動時の追加情報のことを「コマンドライン引数」という。

コマンドライン引数を利用して、様々な追加情報を指定してJavaプログラムを起動することが出来る。
プログラム起動時に指定したコマンドライン引数が、JVMによって配列に変換され、mainメソッド起動時に渡される。

::: note
コマンドライン引数を利用したJavaプログラムの起動
java プログラム名　引数リスト
※引数リストは（）で囲まずに半角スペースで区切って入力する。
:::