Javaのメソッドについて

## メソッドとは
クラスが持つ操作（機能、どんな処理ができるか、命令文など）のまとまりの事。
詳しく書くと特定のクラスやオブジェクトに所属するグループのことで、内容がまとまっている処理や反復する処理など、いくつかの処理を一つにまとめたものを**メソッド**と呼ぶ。

```:メソッドの定義の基本の形
戻り値の型 メソッド名　（引数）{
     処理(命令文)
     return;(戻り値)
  }
```

・**引数**：呼び出し元から受け取る値。「この値を使ってデータを処理して欲しい」というときに、渡す値のことを言う。引数がない場合も（）は記述する。
・**戻り値**：メソッドの処理の後に呼び出し元に返す値。簡単にいうと処理結果のデータ。「retrun」で指定する。戻り値がない（何も返さない）場合は戻り値の型に「void」 と記述する。
・**メソッド名**：変数の名前と同じルールで好きな名前をつけることができる。
```:戻り値を返さない場合
void メソッド名(引数){
    処理(命令文)
}
```

メソッドには
・呼び出す側(呼び出し元)
・呼び出される側
がある
下の写真では左側の１つが呼び出す側（実行用クラス）、右側の３つが呼び出される側（設計図クラス）のイメージ。
![スクリーンショット 2022-11-02 13.32.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2785154/07e1ff63-62a3-9d14-4e57-64342ff34b5a.png)
呼び出す側と呼び出される側では写真の赤矢印の様にそれぞれ繋がっており、メソッドを呼び出す時とメソッドから処理が戻って来る時にデータを渡したり、受け取ったり、戻したりすることができる。
（例えばsetScoreメソッドでは呼び出す側の引数の90と80という値をと呼び出される側に渡している。
getAvgメソッドでは呼び出される側で計算した値を呼び出す側に85.0という戻り値として戻している）

```:上写真のサンプルコード
class Student{
  //メンバ変数（属性）
  String name;
  int engScore;
  int mathScore;

  //メソッド（操作）
  void display(){
    System.out.println(name + "さん");
    System.out.println("英語" + engScore + "点・数学" + mathScore + "点");
  }
  void setScore(int eng, int math){
    engScore = eng;
    mathScore = math;
  }  
  double getAvg(){
    double avg = (engScore + mathScore) / 2.0;
    return avg;
  }
}
```
＊メソッド内で定義される変数のことをローカル変数と呼ぶ。このローカル変数の有効範囲(スコープ)としてはメソッド内だけなので、他のメソッドから別のメソッドのローカル変数にアクセスすることは出来ず、メソッドを抜けるとそのローカル変数は消滅する。

上の写真、サンプルコードの様にメソッドには
・戻り値、引数なしのパターン
・引数があり、戻り値なしのパターン
・戻り値があり、引数なしのパターン
がある。

## 引数と戻り値のないメソッド
```:例文
 class Point {
	int x;
	int y;
	
      //呼び出される側
	 void printPonition() {
		  System.out.println("座標値は(" + this.x +","+ this.y +")です"); 
	  }
     void printPonition2() {
		  System.out.println("座標値は(" + this.x +","+ this.y +")です"); 
	  }
	}

 class Main {
	public static void main(String[] args) {
		Point p1 = new Point();
		p1.x = 10;
		p1.y = 5;
	
　　　　　　　　　　　　　　　　Point p2 = new Point();
		p2.x = 5;
		p2.y = 2;
		System.out.println("p1.printPonitionメソッドの呼び出し"); 
　　　　　　　　　　　　　　　　　//p1のprintPonitionメソッドを呼び出し
	    p1.printPonition();

        System.out.println("--------"); 

　　　　　　　　　　　　　　　　System.out.println("p2.printPonitionメソッドの呼び出し"); 
	    p2.printPonition();
	}
}
```
```:出力結果
p1.printPonition1メソッドの呼び出し
座標値は(10,5)です
--------
p2.printPonition2メソッドの呼び出し
座標値は(5,2)です
```
＊変数名の後ろにドット(.)をつけてメソッド名を記述方法でインスタンスにメソッドを実行させる事もできる
＊「this」は自分自身を表すキーワード。メソッドの中でインスタンス変数を参照するために使用する。


実行はmainメソッドに書かれた処理からJavaの実行が始まるのではMainクラスから始まる。
上から下に向かって順番に処理が実行されていきprintPosition1メソッドの呼び出しが行われると、処理の流れはprintPonition1メソッドの中に記述された命令文に移る。
printPonition1メソッドの中の命令文を実行し終えると、流れは呼び出す側に戻って"------"が出力されprintPosition２メソッドの呼び出しが行われる。
　このように、、処理の流れは途切れることなく命令を１つ１つ実行してされて行く。

## 引数のあるメソッド（戻り値なし）
引数の受け渡しは、メソッド名の後ろのカッコ()を使って行う。
メソッドに引数として渡される値(実引数)を受け取っている変数(仮引数)はこのメソッドの中だけで使用できるローカル変数になる。
複数の引数を指定する場合はカッコの中に「型 変数名」の組をカンマ(,)で区切って記述する。メソッドを呼び出す側も同様に、カッコの中に値をカンマ(,)で区切って記述する。
```:引数のあるメソッドの宣言
void メソッド名(型　　変数（仮引数）);
```


```:例文
class Pont {
	int x;
	int y;
	
	 void printPonition() {
		  System.out.println("座標値は(" + this.x +","+ this.y +")です"); 
	 } 
	 void add(int n, int m ) {   //仮引数としてint nと int mを受けとっている
		 this.x += n;
		 this.y += m;
	 } 
}

class ArgumentsExample {
	public static void main(String[] args) {
		Pont p = new Pont();
		p.x = 10;
		p.y = 5;
		p.printPonition();
		
		p.add(3,4);      //addメソッドに実数として整数の３と４を渡している。
		p.printPonition();
	}
}
```
```:出力結果
座標値は(10,5)です  ←最初にxとyの値を１０と５に設定
座標値は(13,9)です　　　　←addメソッドに整数３と４を渡しているのでxとyにそれぞれが足された結果になる
```
addメソッドに実数として整数の３と４を渡し、仮引数としてint nと int mを受けとる。
int nには３と int mには４が渡しthis.x += n; this.y += m;と記述しているのでそれぞれが足された結果が出力される。

＊引数は渡されてくる値の数だけ記述する必要があり、渡されてきる値と同じデータ型を使って宣言されている必要がある。

## 戻り値のあるメソッド（引数なし）
呼び出し側からメソッドに値を渡すだけでなく、逆にメソッドで処理を行った結果の値を、呼び出し側で受け取ることも出来る。
戻り値を受け取ることによって、ある計算を行った結果や、処理に成功したか失敗したかといった情報を呼び出し側で知ることができる。

メソッドからの戻り値は１つだけ指定でき、その値の型をメソッド名の前に記述する。
戻り値が基本型の場合は、int、double、boolean などの型の名前を記述し、参照型の場合はPoint などのクラス名を記述する。

メソッドで行う処理の最後に、**return**というキーワードに続けて、戻り値を記述する。
注意点としてはreturnの後に返すデータと戻り値のデータ型を必ず合わせないといけない。あっていないとコンパイルの時点でエラーになる。
```:戻り値のあるメソッドの宣言
戻り値の型 メソッド名　（引数）{
     処理(命令文)
     return  戻り値;
}
```

```:例文
class Point {
	int x;
	int y;
	
	//xとyを掛けた結果を返す
	int getXY() {
		return this.x * this.y;
	  }
	}

 class Main {
	public static void main(String[] args) {
		Point p = new Point();
		p.x = 10;
		p.y = 5;
		
		//pのgetXYメソッドの戻り値をint型の変数xyに代入
		int xy = p.getXY();    
	    System.out.println("pのxとyを掛けた結果は" + xy); 

	}
}
```
```:出力結果
pのxとyを掛けた結果は50
```

## 引数と戻り値のあるメソッド
これまでに引数があるメソッドと戻り値のあるメソッドを別々に見てきましたが、引数と戻り値の両方があるメソッドも、宜言出来る。

下記のisSamePositionメソッドは、引数としてPointクラスのインスタンスヘの参照を受け取り、そのインスタンスと自分自身の座標値を比較した結果を戻す。戻り値はboolean型で、座標値が同じであればtrueを、そうでなければfalseを返す。
このメソッドのようにint型やdouble型のような基本型の値だけではなく、インスタンスの参照(参照型)も引数にできます。
```:例文
class Point {
	int x;
	int y;
	
	void muitiply(int n) {
		this.x *= n;
		this.y *= n;
	  }
	
	
	boolean isSamePosition(Point p) {
		if(this.x == p.x && this.y == p.y) {
			return true;
		} else {
			return false;
		}
	}
} 

 class Main {
	public static void main(String[] args) {
		Point p1 = new Point();
		p1.x = 4;
		p1.y = 2;
		
		Point p2 = new Point();
		p2.x = 8;
		p2.y = 4;
		
		if(p1.isSamePosition(p2) == true) {
			System.out.println("p１とp２は同じ座標です" ); 
		} else {
			System.out.println("p１とp２は異なる座標です"); 
		}
		
	   p1.muitiply(2);
	   if(p1.isSamePosition(p2) == true) {
			System.out.println("p１とp２は同じ座標です"); 
		} else {
			System.out.println("p１とp２は異なる座標です"); 
		}
	}
}
```
```:出力結果
p１とp２は異なる座標です
p１とp２は同じ座標です
```
isSamePositionメソッドが受け取る引数はPoin クラスのインスタンスなので、変数p2 を引数に指定出来る。(「Point クラスのインスタンス」と表現しているが、実際にisSamePositionメソッドが受け取るのは「Pointクラスのインスタンスの参照」です)。プログラムコードと結果を見比べると、はじめ、p1の座標は(2, 4) 、p2の座標は(4, 8)で異なる結果だが、途中でp1の座標が(4, 8)に変更され、今度はp1とp2が同じ座標であると判断されたことが確認出来る。

## クラスメソッド(staticメソッド)とインスタンスメソッド
**クラスメソッド(staticメソッド)** とはstatic修飾子がついたメソッドのこと。
static修飾子がついていないメソッドである**インスタンスメソッド**は名前の通り、インスタンスに紐付けられたメソッドであるため、クラスからインスタンスを生成しないと利用することが出来ない。
Javaにおいて通常のメソッドは、クラスをインスタンス化してから使用するがstatic修飾子を付与したクラスメソッドは、クラスのインスタンス化なしに直接呼び出して使用できるメソッドで、クラスに紐付けられたメソッドであり、クラス全体に関連する処理を定義する。

```:クラスメソッドの呼び出し方
クラス名.メソッド名();
//例文
 Student4 stu1 = new Student4("菅原");
    Student4.display();
```

```:インスタンスメソッドの呼び出し方
インスタンス名.メソッド名();
//例文
 Student4 stu1 = new Student4("菅原");
    stu1.display();
```

### クラスメソッド(staticメソッド)とインスタンスメソッドの使い方
クラスメソッド(staticメソッド)の主な使い方はインスタンスの状態に依存しない処理をさせる事。（これを**ユーティリティメソッド** とも呼び、決まり切った処理に用いられる）

インスタンスメソッドは、インスタンス（オブジェクト）に紐づけられたメソッドなのでインスタンス（オブジェクト）ごとで異なる処理をおこなう時に使用する。

例えば、標準API（クラスをまとめたクラスライブラリのことでクラスライブラリに含まれるクラスは、機能や目的ごとにパッケージとして格納されている）のStringクラスで考えると、値を比較する「equals」メソッドはインスタンスメソッド、int型の変数をString型に変換する「valueOf」はstaticメソッドになる。
```
public boolean equals(Object anObject) ← インスタンスメソッド

public static String valueOf(int i) ← staticメソッド
```

インスタンスメソッドである「equals」メソッドは、Stringオブジェクト（インスタンス）と一致しているかを比較するメソッドであり、Stringオブジェクト（インスタンス）の状態に依存している。
```:例文
//equalsメソッドは2つの文字列が等しいかどうかの比較をする
String value = "あああ";
value.equals("いいい"); ← Stringのオブジェクト「value」に依存している
```
それに対し、staticメソッドである「valueOf」メソッドは、int型の変数をString型の変数に変換するメソッドであり、Stringオブジェクト（インスタンス）の状態に依存していない。
```:例文
// valueOfメソッドは引数に指定した様々な型の形をString型の文字列として返すことができる
String newValue = String.valueOf(123); ← Stringのオブジェクトに関係ない処理
// String.valueOfでint型の変数(123)をStringm型のオブジェクトnewValueに変換している
```
このように、staticメソッドは、インスタンスの状態に依存しない処理をさせることが出来る。

### 例文
```:実行クラス
public class UtilitySampleMain {

    public static void main(String[] args) {
        System.out.println("数値チェックの結果：" + UtilitySample.isNumber("あいうえお"));
    }
}
```
```:設計図クラス
import java.util.regex.Pattern;

public class UtilitySample {

    private UtilitySample() {}
    
    /**
     * @param value 検証対象の値
     * @return 結果（true：数値、false：数値ではない）
     */
        
     // 数値チェックをする為のインスタンスの状態に依存しないisNumberメソッド
    public static boolean isNumber(String value) {
        boolean result = false;
        if (value != null) {
            Pattern pattern = Pattern.compile("^[0-9]+$|-[0-9]+$");
            result = pattern.matcher(value).matches();
        }
        return result;
    }
}
```
```:出力結果
数値チェックの結果：false
```
「isNumber」メソッドは正規表現を使い引数の値が数値であるかを判断する処理。(※標準APIのPatternクラスを使用)

また「UtilitySample」クラスには、staticメソッドしか実装していないので、コンストラクタをprivateとし、外部からオブジェクト（インスタンス）を生成できないようにしている。
コンストラクタをprivateにすることで、ユーティリティクラスであることを明確にしている。

## 参考文献
https://www.youtube.com/watch?v=YkD9mo5RVio&t=357s

https://www.youtube.com/watch?v=P9CVQ6IuquM&t=661s