【Java】インスタンス変数とクラス変数とローカル変数

## インスタンス変数とは
インスタンスに属する変数のこと。
```ruby:Java(Main.java)
public class Main {
	int num;//インスタンス変数
	String str;//インスタンス変数
	public static void main(String[] args) {
		/*ソース*/		
	}	
}
```

## インスタンス変数をstaticメソッドから呼び出す。
```ruby:Java(Main.java)
public class Main {
	int num;
	String str;
	public static void main(String[] args) {
		Main obj = new Main();
		System.out.println(obj.num);
		System.out.println(obj.str);
	}	
}
```

結果
```
0
null
```

ここで押さえておきたいのは**インスタンス変数は自動的に初期値が設定される**ことだ。int型は0、String型はnullが設定される。呼び出し時は上記のように```Main obj = new Main();```でインスタンス化してから```obj.num```の形で呼び出す。

## インスタンス変数をインスタンスメソッドから呼び出す
```ruby:Java(Main.java)
public class Main {
	int num;
	String str;
	public static void main(String[] args) {
		Main obj = new Main();
		obj.speak();
	}	
	public void speak() {
		System.out.println(num);
		System.out.println(str);
	}
}
```

結果
```
0
null
```

speakメソッドでnumとstrを呼び出しているが、先ほどと異なるのはインスタンス化しなくてもspeakメソッドから各変数を呼び出している点だ。インスタンスメソッドからだとインスタンス化せずにインスタンス変数を呼び出すことができる。

:::note info
**staticメソッドからインスタンスメソッドを呼び出す場合**
この時もインスタンス化が必要
:::

## クラス変数とは
クラス変数(static変数)はクラスに対して静的に存在する変数である。staticをつけることで実装できる。

```ruby:Java(Main.java)
public class Main {
	static int num;
	static String str;
	public static void main(String[] args) {
		/*ソース*/
	}	
}
```

ではここでもnumとstrを出力しよう。
```ruby:Java(Main.java)
public class Main {
	static int num;
	static String str;
	public static void main(String[] args) {
		System.out.println(num);
		System.out.println(str);
	}	
 }
 ```

結果
 ```
0
null
```

今度はインスタンス化せずに呼び出している。クラス変数はたとえインスタンス化しても1か所からしか用意されないため、インスタンス化せずに呼び出せる。また、別のインスタンスでクラス変数の値を書き換えた場合、**同じクラスのインスタンス内の全てのクラス変数の値も書き換わる**。

```ruby:Java(Main.java)
public class Main {
	static int num;
	static String str;
	public static void main(String[] args) {
		Main obj1 = new Main();
		obj1.num = 10;
		Main obj2 = new Main();
		obj2.num = 100;
		System.out.println(num);//クラス変数num出力
		System.out.println(obj1.num);//オブジェクトobj1のnum出力
	}	
}
```


結果
```
100
100
```

このようにobj1.numも、obj2.numで代入された値が出力された。

## クラス名を使ったクラス変数の呼び出し
以下のようにクラス名.クラス変数でクラス変数を呼び出すことも可能。
```ruby:Java(Main.java)
public class Main {
	static int num;
	static String str;
	public static void main(String[] args) {
		Main obj1 = new Main();
		obj1.num = 10;
		Main obj2 = new Main();
		obj2.num = 100;
		System.out.println(Main.num);//クラス変数num出力
	}	
}

```

結果
```
100
```

## ローカル変数とは
ローカル変数はメソッド内で定義された変数。

```ruby:Java(Main.java)
public class Main {
	public static void main(String[] args) {
		int num;
		String str;
	}	
}
```

それでは各値の初期値を確認しよう。
```ruby:Java(Main.java)
public class Main {
	public static void main(String[] args) {
		int num;
		String str;
		System.out.println(num);
		System.out.println(str);
	}	
}
```

結果
```
Exception in thread "main" java.lang.Error: Unresolved compilation problems: 
	ローカル変数 num が初期化されていない可能性があります
	ローカル変数 str が初期化されていない可能性があります

	at Main.main(Main.java:5)
```

エラーになってしまった。実はローカル変数は**初期値が自動的に設定されない**という特徴がある。そのため、以下のように初期値を設定する必要がある。

```ruby:Java(Main.java)
public class Main {
	public static void main(String[] args) {
		int num = 10;
		String str = "name";
		System.out.println(num);
		System.out.println(str);
	}	
}
```

結果
```
10
name
```

ちなみにローカル変数は存在するメソッド内でしか呼べない。以下のように別のメソッドからは呼び出せないので注意(以下だとクラス変数を呼び出そうとしているが、存在しないためエラーになっている)

```ruby:Java(Main.java)
public class Main {
	public static void main(String[] args) {
		int num = 10;
		String str = "";
		speak();
	}	
	public static void speak() {
		System.out.println(num);
	}
}
```

結果
```
Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
	num を変数に解決できません

	at Main.speak(Main.java:8)
	at Main.main(Main.java:5)
```

## インスタンス変数とローカル変数の名前が同じである場合
例えば以下のように同じ名前のインスタンス変数とローカル変数を用意する。それぞれ初期値を設定し、mainメソッドから呼び出してみよう。この時呼び出されるのはインスタンス変数か、ローカル変数か…？

```ruby:Java(Main.java)
public class Main {
	int num = 20;
	String str = "password";
	public static void main(String[] args) {
		Main obj = new Main();
		obj.speak();
	}	
	public void speak() {
		int num = 10;
		String str = "name";
		System.out.println(num);
		System.out.println(str);
	}
}
```

結果
```
10
name
```

結果はローカル変数が呼び出された。しかし、インスタンス変数を呼び出したい場合はどうすれば良いのか。その時は**this**を使えば良い。

```ruby:Java(Main.java)
public class Main {
	int num = 20;
	String str = "password";
	public static void main(String[] args) {
		Main obj = new Main();
		obj.speak();
	}	
	public void speak() {
		int num = 10;
		String str = "name";
		System.out.println(this.num);//変更
		System.out.println(this.str);//変更
	}
}
```

結果
```
20
password
```

今度はインスタンス変数の値を呼び出せた。なおクラス変数を呼び出す場合も同様である。

ここで注意したいのが、thisは必須でないことだ。ローカル変数がない場合もthis.〇〇で呼び出されるのはインスタンス変数やクラス変数になる。この部分が(個人的に)間違えやすかったので注意。

## まとめ
* インスタンス変数はインスタンスに属する変数
* インスタンス変数はインスタンス化することでstaticメソッドから呼び出せる
* インスタンス変数はインスタンスメソッドからそのまま呼び出せる
* クラス変数はクラスに対して静的に属する変数
* クラス変数はインスタンス化せず呼び出せる
* ローカル変数はメソッド内で定義された変数
* ローカル変数はスコープの範囲外だと呼び出せない
* インスタンス変数とローカル変数の名前が同じである場合、this.をつけるとインスタンス変数を呼び出せる