PythonエンジニアのJava入門～Javaの基礎文法を学ぶ～

# Javaを勉強しよう
普段はもっぱらPythonでの開発（たまにGAS）しかしていないのですが、
業務の都合上、Javaを勉強する必要が出てきてしまいました。

Javaなんて学生以来、もう20年近く触ってません。
IFやFORといった基本構文すら、思い出せない体たらく・・・。

そんなJavaド素人の勉強の記録をノート代わりにQiitaに残していきたいと思います。

# 環境構築
JavaはPythonとは違いスクリプト言語ではないらしい。
そのため、Pythonエンジニアがみんな大好き？JupyterNoteBookが使えないようです。
対話形式で開発できないのか・・・。なんかいきなり不安。

とりあえず、JavaJDK（Javaを開発するためのエンジンのようなもの）と、
EclipseというIDE（開発エディタやらデバッグやらいろいろ入ってるやつ）をインストール。

環境変数はまず、JAVA_HOMEというわかりやすい名前の変数を作って、値にはJDKの場所を指定。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242659/bc5c4b19-577f-b2a2-3d2e-4eb708f85b44.png)

今度は、そのJAVA_HOMEを起点としたbinフォルダを、Pathの変数値に加えてあげればOK！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242659/c91363da-cce2-6562-7e97-f18501142e55.png)



# 基礎文法
### コンソールに出力
うーん。たかだか文字を出力するだけでこんなに文字を打たなきゃいけないとは・・・。
Pythonなら1行で済むのに・・・。

ただ、数値を＋演算子で文字列と結合することができて驚いた。
Pythonだと数値はstrで変換してあげないとエラーになったはず。
JavaではSystem.out.printlnが内部の動きでStringに変換してくれているんだとか。

```Java
public class Main {
    public static void main(String[] args){

        System.out.println("ABC");
        System.out.println("数値を出力" + 123); //123は数値だが、自動的にStringに変換される
    }
}
>>>ABC
>>>数値を出力123
```

### 変数の宣言
変数にはデータの型を宣言する必要がある。もし忘れたらエラーで怒られる。
当然Pythonにはそんなもの不要。
これは慣れるまで面倒くさいぞ・・・。
```Java
public class Main {
    public static void main(String[] args){

        String mystr = "hello";
        System.out.println(mystr);
    }
}
>>>hello
```

ちなみに、変数だけ宣言して初期化していない状態だとコンパイルエラーを起こす。
（他のクラスの初期化されていないフィールド値をメソッドで取得できるんだけど、取得するとString型だとNull、int型だと0でなぜか初期化されてる。なんでなん。）
```Java
public class Main {
    public static void main(String[] args){
        //変数を初期化しないで使おうとするとエラー。
        String mystr;
        System.out.println(mystr);
    }
}
```


### 型の変更
うわー、わかりずらい。そして文字が多い。
(int)のようにかっこで囲う型変換の方法をキャストというらしい。
ただ、この方法で型変換をすると、データの欠落（下記場合だと、4.5なのに4と表現され0.5が欠落する）を誘発する。
可能なら避けておいたほうがいいらしい。
```Java
public class Main {
 
    public static void main(String[] args) {
    	String s1, s2, s3;
    	int a1;
    	
    	//文字列
    	s1 = "a";
    	s2 = s1 + "ddd";
    	
    	//数値を文字列に変換
    	s3 = String.valueOf(10);

    	//4.5をinteger型にキャスト変換（キャストはデータの欠落を招くので良い記載とは言えない）
    	a1 = (int)4.5;

    	System.out.println(s1);
    	System.out.println(s2);
    	System.out.println(s3);
    	System.out.println(a1);    	
    }
}

>>>a
>>>addd
>>>10
>>>4
```

### IF文
これはそんなに違和感ない。
```Java
public class Main {
    public static void main(String[] args){

        int flg = 10;
        if(flg > 0){
            System.out.println("flg:" + flg);
        }
    }
}
>>>flg:10
```

### FOR文
これはPythonと比べると明らかに文字数多いなー。
```Java
public class Main {

	public static void main(String[] args) {
		for(int i=1; i<=3; i=i++) {
			System.out.println(i);
		}
	}
}

>>>1
>>>2
>>>3
```

### 拡張FOR文
こっちの方法だと、index番号が溢れて参照エラーを起こすといったトラブルがないので良いらしい。
Pythonちっくな書き方なので、Python触った人だとこっちのほうが扱いやすいかも。
```Java
public class Main {
	public static void main(String[] args) {
		int myarray[] = {1,2,3};
		for(int a : myarray) {
			System.out.println(a);
		}
	}
}
>>>1
>>>2
>>>3
```


### 配列
Pythonでは配列とリストというのは同じようなものだが、
Javaだと明確に切り分けて考えられているらしい。
予め入れるデータ型も決めなきゃいけないのでPythonに比べて窮屈に感じるなぁ。
```Java
public class Main {

	public static void main(String[] args) {
		int n[] = {3,4,5,6};
		String s[] = {"ABC", "EFG"};
		
		for (int i=0; i<n.length; i++) {
			System.out.println("n[" + i +"]は" + n[i]);
		}

		for (int i=0; i<s.length; i++) {
			System.out.println("s[" + i +"]は" + s[i]);
		}
		System.out.println("終了");
	}
}
>>>n[0]は3
>>>n[1]は4
>>>n[2]は5
>>>n[3]は6
>>>s[0]はABC
>>>s[1]はEFG
```

### リスト
なんと、リストを使う場合、ライブラリをインポートする必要がある。
（そんくらい標準で入れといてくれよ！）
<>で予め入れておく型を宣言しておくことができる。（これはPythonには無かった便利機能かも）
```Java
import java.util.*;

public class Main {

	public static void main(String[] args) {
		
		//文字列のリストを作成
		ArrayList<String> sl = new ArrayList<String>();
		sl.add("1");
		sl.add("2");
		sl.add("3");		
	
		//数値のリストを作成
		ArrayList<Integer> il = new ArrayList<Integer>();
		il.add(4);
		il.add(5);
		il.add(6);
		
		for (String s : sl) {
			System.out.println(s);
		}
		
		for (Integer i : il) {
			System.out.println(i);
		}
	}
}
>>>1
>>>2
>>>3
>>>4
>>>5
>>>6
```

### 辞書
これもリスト同様にインポートが必要。
```Java
import java.util.*;

public class Main {

	public static void main(String[] args) {
		
		HashMap<String, Integer> map = new HashMap<String, Integer>();
		String nengo[] = {"A","B","C","D"};
		
        map.put(nengo[0], 1000);
        map.put(nengo[1], 1001);
        map.put(nengo[2], 1002);
        map.put(nengo[3], 1003);
        
        for (String s : nengo) {
        	System.out.println(s+"は、"+map.get(s));
        }
	}
}
>>>Aは、1000
>>>Bは、1001
>>>Cは、1002
>>>Dは、1003

```

### 例外処理
例外処理。これはPythonと書き方はほぼ同じなので全く違和感なし。
```Java
public class Main {
 
    public static void main(String[] args) {
        try{
            int n[] = {1,2,3};
            System.out.println(5 / 0); //ArithmeticException eに飛ばされる                
            System.out.print(n[4]); //Exception eに飛ばされる         
        }
        catch(ArithmeticException e){
            System.out.println();
            System.out.println("0による割り算発生");
        }
        catch(Exception e){
        	System.out.println("0除算以外のエラー");
        }
        finally{
            System.out.println("終了");
        }
    }
}
```

### メソッドの呼び出し
なんとJavaでは引数の型さえ違えば、メソッド名の重複が許されてしまう。
この重複してしまう定義のことをオーバーロードというらしい。
呼び出し側のほうで使う引数の型によって自動で呼び出すメソッドを変えてくれるとのこと。
この機能はPythonには無いのでビックリ。
```Java
public class Main {
	
	//	メソッド
	public static int add(int a, int b) {
		return a + b;
	}
	
	//	メソッド(オーバーロード)	
	public static String add(String s1, String s2) {
		return s1 + s2;
	}

	public static void main(String[] args) {
		
		int a = 1;
		int b = 2;
		System.out.println(add(a,b));
		
		String s1 = "aaa";		
		String s2 = "123";
		System.out.println(add(s1,s2));
	}
}
>>>3
>>>aaa123
```



# クラス
### 一番単純なクラスの使い方
次はクラスについて。
Pythonではオブジェクト指向で作りこんでもいいし、作らなくてもいいという考え方に対し、
Javaはガッツリとしたオブジェクト指向な作り込みを求めてくる言語。

あと、staticやらpublicやら他のクラスファイルからのアクセス制御を厳密に設定できるらしい。
それと、パッケージという概念もあり、同じパッケージ内であれば、importせずに他のクラスファイルにアクセスすることが可能になる。

下記例は、CalcとCalcLogicを同一パッケージに入れてあり、
CalcからCalcLogicを呼び出している。

Calcが所謂メイン関数になるが、他の人はそれを知らないので渡す際にはどれがメインになるのかを伝える必要がある。


```Java:(CalcLogic)
package class_book_01;

public class CalcLogic {
	public static  int tasu(int a, int b) {
		return (a + b);
	}
	public static  int hiku(int a, int b) {
		return (a-b);
	}
}
```

```Java:(Calc)
package class_book_01;

public class Calc {
	public static void main(String[] args) {
		
		//staticメソッドは、クラス名.メソッド名で呼び出し可能
		System.out.println(CalcLogic.tasu(1,3));
		System.out.println(CalcLogic.hiku(10,5));
		
		//インスンスを作成したうえでメソッドを呼び出す
		CalcLogic c = new CalcLogic();
		System.out.println(c.tasu(1,3));
		System.out.println(c.hiku(10,5));		
	}		
}
```
コンパイルする際には、class_book_01のフォルダを新規に作成し、
class_book_01に作成したCalc.javaと、CalcLogic.javaファイルをコピーする。

コピーした後、コマンドプロンプトを起動して下記コマンドを入力。
```javac class_book_01\Calc.java```
すると、Calc.classだけじゃなく、CalcLogic.classも作成される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242659/ef9d4033-e1dd-da82-f78f-2593dc6309af.png)

実行の際は、パッケージフォルダの親フォルダまで移動し、
<b>```java パッケージ名.クラス名```</b>で実行する。（重要！）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242659/fc614ad4-8732-b17b-a8f6-81c5455a3023.png)

パッケージフォルダの中まで行ってからjavaコマンドでクラスファイルを直実行しようとすると下記のようにエラーになる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242659/676eed54-186f-47b3-c38f-51da4b26db13.png)

各機能ごとに部品を分割するという考えてこんな仕組みにしているんだろうなとは思うけど、
Pythonと比べて無茶苦茶複雑・・・。

### 複数階層あるパッケージの場合
パッケージが複数階層になっている場合も基本的な考え方は同じ。
たとえば、workというパッケージがあり、ここに他の全てのクラスを操作するためのMainクラスがあったとする。
そして、workの下には更にcommentというパッケージがあり、その下にいくつかのjavaファイルがあったとする。
※下記はイメージ図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242659/30c331a1-f501-b98c-f8e5-e1797fae281d.png)

これをコンパイルする場合は、workフォルダごと、任意のフォルダにコピーし、
workフォルダの親フォルダに行き、コンパイル→実行すればOK

ちゃんとcommentパッケージにあるクラスファイルも実行されていることが分かる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242659/6429e38a-6ebb-8292-23ce-5c058e4de5f1.png)

とりあえず、基礎文法はこんな感じかな。
（不足分があったら適時追記しておこう）
次回はクラスの詳細な機能やオブジェクト指向について掘り下げて勉強してみる。