Java基本文法

※ 注意：Java 8を想定しています。
## **型**
#### 型に関して
+ int, longなどの型を基本型、値型、プリミティブ型という
+ StringやIntegerなどの型を参照型、オブジェクト型、ラッパークラスという
+ 参照型はさらに、イミュータブル(不変)とミュータブル(可変)に分けられる。<br>ほとんどがミュータブルで、StringやLocalDate, LocalDateTimeはイミュータブルという認識。<br>イミュータブルは直接値を変更できず、再代入する必要がある。

#### 型変換に関して


![スクリーンショット (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100765/480c44c7-73cd-747d-7d5a-c51da61e11be.png)



+ 右から1つ左に型変換するなら型キャストが必要。例：int a = (型名) b
+ 左から右へは暗黙の型変換
+ プリミティブ型からラッパークラスへの型変換をオートボクシング、逆をアンボクシングという → [リンク](https://qiita.com/chihiro/items/870eca6e911fa5cd8e58)


## 変数と定数
#### **宣言**

```java

/* 変数宣言 */
boolean varA; // 宣言のみ
varA = true; //  代入のみ
Class varI //   宣言のみ(参照型)
varI = new Class() // 代入のみ(参照型) 

/* 定数宣言 */
static final data_type varJ = valA; // (static + ) final修飾子

```


## 配列

#### **固定長配列**
```java
/* 宣言 */
data_typeA[] arrayA = new data_typeA[index_max_value];
data_typeB[] arrayB = {valA, valB, valC, valD, valE};
data_typeC[] arrayC = new data_typeC[] {valF, valG, valH};
data_typeD arrayD[]; // 変数名に[]をつけても可
// X arrayD = {valI, valJ, varl}
arrayD = new data_typeD[]{valI, valJ, varl}
data_type[][] arrayE; // 2次元配列 → date_type[] arrayE[]でもよい。
arrayE = new date_typeE[i][]; // 添え字は2つ目省略可。1つ目は不可。

/* arraysクラス */
Arrays.toString(arrayD); // "[valI, valJ, vall]"
Arrays.sort(arrayD);     // {vall, valJ, valI}
```

#### **可変長配列(コレクション)**
```java
/* List(インターフェース) */
// X List<data_typeA> listA = new List<>();
List<data_typeA> listA =  new ArrayList<>();
List<data_typeB> listB =  new LinkedList<>();
List<data_typeC> listC =  new CopyOnWriteArrayList<>();
List<data_typeD> listD = Arrays.asList(valA, valB); // 読専
listD.add(valD);         // 末尾に追加
listD.add(indexA, valE); // 途中に挿入
listD.set(indexA, valF); // 置換
listD.get(indexA);       // 値の取得
listD.indexOf(valF);     // 位置の取得
listD.size();            // 要素数の取得
listD.contains(valF);    // 存在の確認
listD.remove(valF);      // 削除

/* --- 以下Listの実装クラス ------------------------------- */
/* ArrayList .. 検索に強い */
// ArrayListにしか存在しないメソッドを使う場合は下記で宣言(以下同様)
ArrayList<data_typeE> listE =  new ArrayList<>();
ArrayList listF = (ArrayList<data_typeE>)listE.clone(); // コピー

/* LinkedList .. 追加/削除に強い */
LinkedList<data_typeG> listG =  new LinkedList<>();
listG.push(); // 先頭に追加
listG.pop();  // 先頭から削除

/* CopyOnWriteArrayList .. 同期化不要/マルチスレッドに強い */
CopyOnWriteArrayList<data_typeH> listH =  new CopyOnWriteArrayList<>();

```

#### **連想配列(コレクション)**
```java
/* Map(インターフェース) */
// X Map<Integer, data_typeA> mapA = new Map<>();
Map<Integer, data_typeA> mapA = new HashMap<>();
Map<Integer, data_typeB> mapB = new LinkedHashMap<>();
Map<Integer, data_typeC> mapC = new ConcurrentHashMap<>();
Map<Integer, data_typeD> mapD = new TreeMap<>();

mapA.put(keyA, valA);     // 末尾に追加
mapA.put(keyA, valB);     // 置換
mapA.get(keyA);           // 値の取得
mapA.size();              // 要素数の取得
mapA.containsKey(keyA);   // キーの検索
mapA.containsValue(valB); // 値の検索
mapA.remove(keyA);        // 削除

/* --- 以下Mapの実装クラス ------------------------------- */
/* HashMap ... 検索に強い */
HashMap<Integer, data_typeE> mapE = new HashMap<>();

/* LinkedHashMap .. 挿入した順番を保持 */
LinkedHashMap<Integer, data_typeF> mapF = new LinkedHashMap<>();

/* ConcurrentHashMap .. 同期化不要/マルチスレッドに強い */
ConcurrentHashMap<Integer, data_typeG> mapG = new ConcurrentHashMap<>();

/* TreeMap .. キーの大小を意識した部分集合 */
TreeMap<Integer, data_typeH> mapH = new TreeMap<>();
```

#### **集合(コレクション)**
```java
// X Set<data_typeA> setA =  new Set<>();
Set<data_typeA> setA =  new HashSet<>();
Set<data_typeB> setB =  new LinkedHashSet<>();
Set<data_typeC> setC =  new TreeSet<>();
Set<data_typeD> setD =  new HashSet<>(ListA); // List->Set

setD.add(valA);      // 値の追加/上書き
setD.remove(valB);   // 値の削除
setD.size();         // 要素数の取得
setD.contains(valC); // 値の検索

/* --- 以下Setの実装クラス ------------------------------- */
/* HashSet .. 検索に強い */
HashSet<data_typeA> setA =  new HashSet<>();

/* LinkedHashSet .. 追加/削除に強い */
LinkedHashSet<data_typeB> setB =  new LinkedHashSet<>();

/* TreeSet .. キーの大小を意識した部分集合 */
TreeSet<data_typeC> setC =  new TreeSet<>();
```
#### ほか
###### Queueとその実装型 ... FIFO
```java
Queue<data_typeA> queueA = new ArrayBlockingQueue<>(intA);
queueA.offer(valA); // 追加
queueA.peek();      // 出力
queueA.poll();      // 出力/削除
```
###### Dequeとその実装型 ... Queueの拡張型。両端から追加削除可能。
```java
// LinkedListはListとDequeの実装型
Deque<data_typeA> dequeA = new LinkedList<>();
dequeA.offerFirst(valA); // 先頭に値の追加
dequeA.offerLast(valB);  // 末尾に値の追加
dequeA.peekFirst(valC);  // 先頭の値の出力
dequeA.peekLast(valD);   // 末尾の値の出力
dequeA.pollFirst(valE);  // 先頭の値の出力/削除
dequeA.pollLast(valF);   // 末尾の値の出力/削除
```

参考：<a href="https://qiita.com    /yoshi389111/items/0ca5c9ecd55914821948">[Java] スタックキューのメモ</a>

## 分岐

#### **If文**
```java

if (conditionA){ 
    statementA // 文、処理
} else if (conditionB) {
    statementB // 文、処理
} else if (!conditionC) {
    statementC // 文、処理
} else {
    statementD // 文、処理
}

/* {}省略 ... ネスト内に文を一行のみ記載可能 */
if (conditionA)
    statementA // 文、処理
else
    statementB // 文、処理

```

#### **switch文**
```java

switch (varA) {
    case valA:     // varA = valA の場合
        statementA // 文、処理
        // break文 ... コードブロックの実行を途中終了
        break;
    case valB:
    case valC:     // varA = valB, valC の場合
        statementB // 文、処理
        break;
    case default   // varA = valA,valB,valC 以外の場合
        statementC // 文、処理
        break;
	/* caseの順は制限はない。defaultが先頭でも可(非推奨) */
}
```

## 反復

#### **For文**
```java
/* 指定した回数文繰り返す */
for (data_type varA = valA; varA <= valB; valC++) {
    statementA // 文、処理
}
/* for(int a, int b, a < 3, a++, method()){ のように 
初期値と更新値は複数定義が可能。更新値はメソッド呼び出しも可能) */

/* 配列コレクションからの繰り返し */
for (data_type varB : collectionA) {
    statementB // 文、処理
}

/* forEachとラムダ式の組み合わせ(collectionBの要素を出力する) */
collectionB.forEach(varC -> System.out.println(varC)); 
```

#### **While文(Do-While文)**
```java
/* 条件式がTrueの間繰り返す */
while (conditionA) {
    statementA // 文、処理
} 

do { 
    statementB // 文、処理 
} while (conditionB);

/* 条件式がTrueになるまで繰り返す場合 */
while (!conditionC){
    statementC // 文、処理
}

do { 
    statementD // 文、処理 
} while (conditionD);

```

#### **Break文とContinue文**

```java
X: // ラベル
while (conditionA) {
    switch(varA){
        case valA: // statementA,Bを通る
            statementA // 文、処理
        case valB: // statementBのみ通る
            statementB // 文、処理
            /* break文 ... コードブロックの実行を途中終了 */
            break;
		case valC:
		    break X; // 1行目「X:」のところにジャンプ(Whileを抜ける)
        default:
            statementC // 文、処理
            /* continue文 ... 実行制御を次の反復処理に移す */
            continue;
    } 
}
```

## 例外処理 ... エラーをチェックする

```java
/* try ... 対象処理 */
try{
	statementA
/* catch ... 例外処理 */
} catch (xxxException e){
	e.printStackTrace();    // 例外メッセージ(基本これ)
	e.getClass().getName(); // 例外クラス名のみ
	e.getMessage();         // 例外詳細メッセージのみ
	StackTraceElement[] ste = e.getStackTrace(); // 例外の一覧
/* finally ... try/catch のあと(try/catchにreturnがあっても) 必ず行う処理。 */
} finally{
	statementB // 文、処理
}
// try-catch-finallyの順番は変更不可。try-catch, try-finallyなどの省略可。

/* throw句 ...  例外の強制的な生成 */
throw new ExceptionClassA();

/* throws句 ... 呼び出し元にエラーを渡す */
public class Main throws Exception { // mainにつけると例外がどっかいく 
```

#### 例外の種類

|クラス|概要|発生タイミング|
|:---|:---|:---|
|Error|実行環境のトラブルなど、プログラムからは対処しようのないエラー|実行時(非検査項目)|
|Exception - RuntimeException|プログラムを正しく書けば防げるException|実行時(非検査項目)|
|Exception - 上記以外|プログラムを正しく書いても防げないException。throws必須|コンパイル時(検査項目)|

## クラス

#### **クラスの基本**
```java
package	scope1.packageA;   // パッケージ宣言
import scopeB.libC;        // 別パッケージBのlibCをインポート
import static scopeC.libD.methodA; // 別パッケージCのlibDのmethodAメソッドをstaticインポート

public class ClassA{
    /* 始めに呼ばれるメソッド */
	// mainの引数パターンは他に(String... args), (String args[])
	public static void main(String[] args){
		ClassB instanceA = new ClassB("naiyo");
		System.out.println(instanceA.getMethodA());
	}
}

private class ClassB{
	private data_type _fieldA;
    
	/* staticイニシャライザ ... staticアクセス、インスタンス生成など、
	　　　　　　　　　　　　　　　初めてクラスがロードされた時に最初に実行 */
	static {
        // 初期化処理など。
	}

	/* 初期化ブロック ... 毎回インスタンスが生成された時に最初に実行 */
	{
		// 初期化処理など
	}

	/* コンストラクタ ... 毎回インスタンスが生成された時に最初に実行 */
	Class2(){
        this._fieldA = "";
    }

    /* 順番は staticイニシャライザ -> 初期化ブロック -> コンストラクタ */

    /* セッター */
	data_type setMethodA(data_type varB){
		this._fieldA = varB; // 引数とフィールド名は同じ
	}

    /* ゲッター */
	data_type getMethodA(){
		return this._fieldA;
	}
}

```

#### **修飾子**
```java
/* アクセス修飾子 */
private class1{}         // 同クラスからのみアクセスできる
protected class class1{} // 同クラスとサブクラスからのみ
class class1{}           // 同パッケージからのみ
public class class1{}    // 全てのクラスから

/* 他修飾子 */
abstract      // 抽象クラス、抽象メソッド
static        // クラス名.メンバで呼び出し可, static以外のメンバにアクセス不可
final         // 上書きされない(定数)
synchronized  // 複数プロセス時排他制御を行う
native        // ネイティブクラス、ネイティブメソッド
strictfp      // IEEE754に則って浮動小数点数を演算処理する
transient     // シリアライズの対象から除外
volatile      // フィールド値のキャッシュを抑制する
const         // 多言語の定数修飾子、Javaでは使用せず

/* アノテーション */
@Deprecated       // 非推奨であることを明示
@Override         // 上書きしていることを明示
@SuppressWarning  // 警告表示を抑制

/* 順番 */
@Annotation 
public protected private
abstract static final synchronized native strictfp
```

## **継承(多態性)**
#### **継承の基本**
```java
/* 親クラス */
protected class ClassA{
	protected data_type fieldA;
	protected Class1(data_type varA){　// 親クラスのコンストラクタ
        this.fieldA = varA;
    }  
	protected void methodA(data_type varB){　// 親クラスのメソッド
        statementA
    } 
}

/* 子クラス */
public class ClassB extends ClassA{
	public ClassB(data_type varC){ // 子クラスのコンストラクタ
		super(varC); // 親クラスのコンストラクタを呼び出す
	}
	@Override // オーバーライド修飾子(前述)
	public void methodA(data_type var2){
    	statementB // 文、処理
	}
}
```

#### 抽象クラス ... 雛型、共通の処理を実装したい
```java
/* 抽象クラス */
protected abstract class ClassA{
	protected data_type fieldA;
	public Class1(data_type varA){
		this.fieldA = varA
	}
	// オーバーライドされる前提のメソッド(抽象メソッド)
	public abstract void methodA(data_type varB); 
}
/* 子クラス */
protected abstract class ClassB{
	@Override
	public abstract void methodA(data_type varB){
    	statementA // 文、処理
	}
}
```
#### インターフェース ... 抽象メソッドと定数しか定義ができない(原則)
```java
/* インターフェース */
public interface InterfaceA{
	/* 基本的に以下のように、型の羅列を行う */
	data_type CONST_A = "CONST_A"; // public static finalは省略可
	data_type methodA(data_type varA);

	/* ---- 以下Java8から追加。個人的に非推奨(複雑なため) ---- */
	// defaultメソッド ... 抽象クラスの通常メソッドのようなもの
	default void methodB(data_type varB){
    	statementA // 文、処理
	}
	// staticメソッド ... インスタンスなしで呼び出し可
	public static methodC(data_type varC){
    	statementB // 文、処理
	}
}

/* 子クラス */
public class ClassB extends InterfaceA{
	public static void main(String[] args){		
		@Override
		public static methodB(data_type varB){
			// Ｘ ClassB.methodC
			// Ｘ @Override methodC
			InterfaceA.methodC(Interface1.CONST_A);
		}
}
```

## **色々なクラス**
#### **ジェネリックスクラス(テンプレート)**
```java
public class GenericClassA<TYPE>{
	private TYPE _fieldA;
	GenericClassA(TYPE varA){
		this._fieldA = varA;
	}
	TYPE setMethodA(TYPE varB){
		this._fieldA = varB;
	}
	TYPE getMethodA(){
		return this._fieldA;
	}
}

/* ジェネリックメソッド */
public class ClassA{
	public static <TYPE> ArrayList<TYPE> GenericMethodA(TYPE val1){
	}
}
```

#### **インナークラス**
```java
public class ClassA{
	/* staticメンバークラス ... */
	static class MemberClassA{}

	/* 非staticメンバークラス ... */
	class MemberClassB{}

	public static void main(String[] args) {
		/* ローカルクラス ... */
		class LocalClassC{
			public void localMethod(){}
		}
		LocalClassC localClassC = new LocalClassC();
		localClassC.localMethod();

		/* 匿名クラス ... 定義とインスタンス化を同時にできる */
		// ArrayList型を継承した匿名クラス
		List<data_typeC> list = new ArrayList<data_typeC>() {
			public data_typeC method3() {
				statements // 文、処理
			}
		};
	}
}

public class ClassB{
	public static void main(String[] args){
		// staticメンバークラス呼び出し
		ClassA.MemberClassA cAcA = new ClassA.MemberClassA();
		// 非staticメンバークラス呼び出し
		ClassA cA = new ClassA();
		ClassA.MemberClassB cAcB = cA.new MemberClassB();
	}
}
```
#### **モジュール(Java9)**
```java:module-info.java
module moduleA{ // module-info.javaというファイルに記載。
    export moduleA.lib; // 本モジュール内のライブラリを公開する
    requires moduleB;   // 本モジュールが必要とするモジュールを記載する
}
```

参考：[モジュールシステムを学ぶ](https://qiita.com/opengl-8080/items/93c8e0cf58654d5f73cb) / [Java Modules](http://tutorials.jenkov.com/java/modules.html)

##### enum(列挙型)

```java
public enum EnumA{
	/* 基本 */
	elmA, elmB;
	/* 応用 - メンバ、変数、メソッドの追加 */
	elmC(0), elmD(1);
	private final int fieldA;
	private setElmA(int varA){
        this.fieldA = varA;
    }
	public int getVal(){
        return fieldA;
    }
	public void outVal(){ // values() .. 全enum要素のリスト
		for (Enum2 enums : values()) { 
			System.out.println(enums.getVal()); // 0, 1
		}
	}
}
```

## **ラムダ式(Java8)**
#### 書き方
```java
/* (args) -> { statements // 文、処理 } */
// 一つの場合は args -> statements
Collections.sort(listA, (a,b) -> {return b - a;});
```

#### メソッド参照
```java
/* スタティックメソッド(class::method)*/
// list.forEach(i -> String.toString(i)));
list.forEach(String::toString);

/* メンバーメソッド(this::method) */
// list.forEach(i -> this.toString(i)));
list.forEach(this::toString);

/* ジェネリックメソッド(class::<type> method) */
// list.forEach(i -> ClassA<typeA> methodA(i);));
list.forEach(ClassA::<typeA> methodA);

/* インスタンスメソッド(object::method) */
// list.forEach(i -> System.out.print(i));
list.forEach(System.out::print);

/* コンストラクタ(class::new) */
ClassA instanceA = classA::new;
```

#### 関数型インターフェース <br>... 抽象メソッド1つしか定義されていない等、条件を満たすとラムダ式やメソッド参照の代入先になれる
```java
@FunctionalInterface
public interface FuncInterfaceA {
	public data_typeA method(data_typeA varA);
}

/* メジャーな標準の関数型インターフェース */
// Function.apply()    値を変換する
Function<String, Integer> func = x -> x.length();
System.out.println(func.apply("mojisu")); // 6

// Predicate.test()    判定を行う
Predicate<Integer> condA = i -> i != 0 ;
Predicate<Integer> condB = i -> i % 2 == 0 ;
condA.test(2);            // true
condA.negate().test(1);   // false (negate..否定)
condA.or(condB).test(1);  // true  (or判定)
condA.and(condB).test(1); // false (and判定)

// Supplier.get()      引数なしで値を返す
Supplier nowTime = () ->  LocalDateTime.now();
System.out.println(nowTime.get()); // 2020-01-22 12:34:56

// Consumer.accept()   引数を元に処理 
Consumer<String> printA = str -> {
	System.out.println("printA: " + str);
}
Consumer<String> printA = str -> {
	System.out.println("printB: " + str);
}
Consumer<String> printAll = printA.andThen(printB); // 結合する
printAll.accept("" + System.currentTimeMillis());
```

参考：[Java8のラムダ式を理解する](https://qiita.com/sano1202/items/64593e8e981e8d6439d3) / [Java関数型インターフェース](http://www.ne.jp/asahi/hishidama/home/tech/java/functionalinterface.html)

## **ストリームAPI(Java8)**
```java
// Streamを生成
Stream<data_typeA> streamA = listA.stream(); // stream()をつける
IntStream intStreamA = IntStream.range(1,5); // 数値からStreamを作成
// 中間操作
streamA.filter(p -> p.length() > 5); // 絞り込む
streamA.map(p -> "[" + p + "]"); // 置き換える
// 終端操作
List<data_typeB> listB = streamA.collect(Collectors.toList()); // 変換
// 出力
listB.forEach(System.out::println);

/* ワンライナー */
listA.stream()
	.filter(p -> p.length() > 5)
	.map(p -> "[" + p + "]")
	.collect(Collectors.toList())
	.forEach(System.out::println);

```
#### 中間操作メソッド

|メソッド|処理内容|例|
|---|---|---|
|map|要素を別の値に置き換える|.map(s-> s.getMethod())|
|flatmap|要素のStreamを結合する|.flatmap(s -> s2.stream())|
|filter|合致した要素を絞り込む|.filter(s -> s.equals(1)|
|limit|指定した件数に絞り込む|.limit(2)|
|distinct|ユニークな要素のみに絞り込む|.distinct()|
|sorted|要素を並び替える|.sorted((s1,s2) -> s2-s1)|
|range|末尾の値を含まず数列を作る|IntStream.range(1,5)|
|rangeClosed|末尾の値を含み数列を作る|IntStream.rangeClosed(1,5)|

#### 終端操作メソッド

|メソッド|処理内容|例|
|---|---|---|
|forEach|繰り返し処理をする|.forEach(System.out::println);|
|collect|結果を作成する|.collect(Collectors.toList());|
|toArray|配列に変換する|.toArray(String[]::new);|
|reduce|値を集約する|.reduce((val1,val2) -> val1.add(val2));|
|toList|Listにして返す|.collect(Collectors.toList());|
|toSet|Setにして返す|.collect(Collectors.toSet());|
|joining|区切り文字で結合する|.collect(Collectors.joining(","));|
|groupingBy|要素をグループ分けする|.collect(Collectors.groupingBy(s -> s.length()));|
※ あくまでメモなので、間違いがあるかもしれないですがご了承ください