【Java】Optionalクラスの使い方　


##Optionalクラスとは？
Optionalクラスは、メソッドの処理結果を扱うためのクラスです。
このクラスを利用することで例外処理に関するコードを減らすことが出来ます。
Optionalクラスはファクトリメソッドです。なので、インスタンスを生成すためにはメソッドを使います。

##Optionalクラスのインスタンス生成メソッド
インスタンスを生成する方法として２つあります。

####引数の値がnull入る可能性がない場合
ofメソッドを利用します。

```Sample.java
import java.util.Optional;

public class Sample {
	public static void main(String[] args) {
	Optional <String> sample = Optional.of("こんにちは");
	System.out.println(sample);
	}
}
```
```
Optional[こんにちは]
```

####引数の値がnull入る可能性がある場合
ofNullableメソッドを利用します。

```Sample.java
import java.util.Optional;

public class Sample {
	public static void main(String[] args) {
	Optional <String> sample = Optional.ofNullable(null);
	System.out.println(sample);
	}
```
```
Optional.empty
```

##インスタンスが値を持っているか調べるメソッド
####isPresent
値を持っていればture,持っていなければfalseを返します。
値を持っているかを確認するメソッドです。

```Sample.java
import java.util.Optional;

public class Sample {
	public static void main(String[] args) {
	Optional <String> sample = Optional.of("こんにちは");
	if(sample.isPresent()) {
		System.out.println(sample.get());
	}
	}
}
```
```
Optional[こんにちは]
```
####isEmpty
空かどうかを確認するメソッドです。

```Sample.java
import java.util.Optional;

public class Sample {
	public static void main(String[] args) {
	Optional <String> sample = Optional.empty();
	if(sample.isEmpty()) {
		System.out.println("空");
		return;
	}
	System.out.println(sample.get());
	}
}
```
```
空
```
####orElseメソッド
値を持っていれば、その値を返します。
値を持っていなければ、引数で指定したものを返します（固定値）。

```Sample.java
import java.util.Optional;

public class Sample {
	public static void main(String[] args) {
	Optional <String> sample = Optional.empty();
	System.out.println(sample.orElse("empty"));
	}
}
```
```
empty
```

####orElseGetメソッド
値を持っていれば、その値を返す。
値を持っていなければ、引数で指定したものを返します（ラムダ式で実行して、その結果を戻す)。

```Sample.java
import java.util.Optional;

public class Sample {
	public static void main(String[] args) {
	Optional <String> sample = Optional.empty();
	System.out.println(sample.orElseGet(() -> "empty"));
	}
}
```
```
empty
```

####orElseThrowメソッド
値が空の場合、意図的に例外を出すことができます。

```Sample.java
import java.util.Optional;

public class Sample {
	public static void main(String[] args) throws Exception{
	Optional <String> sample = Optional.empty();
	System.out.println(sample.orElseThrow(() -> new Exception()));
	}
}
```
```
Exception in thread "main" java.lang.Exception
	at innerclass.Sample.lambda$0(Sample.java:8)
	at java.base/java.util.Optional.orElseThrow(Optional.java:408)
	at innerclass.Sample.main(Sample.java:8)
```


##インスタンスから値を取り出さずに処理をしたい場合
####インスタンスに値がある場合
ifPresentメソッド
Consumer型のラムダ式を受け取り、Optionalが値を持っていなければ、引数に渡して、ラムダ式を実行します。

```Sample.java
import java.util.Optional;

public class Sample {
	public static void main(String[] args) throws Exception{
		Optional<String> sample = Optional.of("test");
		sample.ifPresent((str) -> System.out.println(str));
	}
}
```
```
test
```
####インスタンスに値がない場合
ifPresentOrElseメソッド
値がある場合は第１引数で指定したラムダ式、値がない場合は第２引数で指定したラムダ式を実行します。

```Sample.java
import java.util.Optional;

public class Sample {
	public static void main(String[] args) throws Exception{
		Optional<String> sample = Optional.empty();
		sample.ifPresentOrElse(
				(str) -> System.out.println(str),
				() -> System.out.println("empty"));
	};
}
```

```
empty
```


##参照を戻すメソッド
####getメソッド
Optionalのインスタンスから値を戻します。

```Sample.java
import java.util.Optional;

public class Sample {
	public static void main(String[] args) {
	Optional <String> sample = Optional.of("こんにちは");
	System.out.println(sample.get());
	}
}
```
```
こんにちは
```
####mapメソッド
処理結果を持ったOptionalのインスタンスを新たに生成し、その参照を戻します。

```Sample.java
import java.util.Optional;

public class Sample {
	public static void main(String[] args) throws Exception{
	Optional<String>sample = Optional.of("test");
	Optional<String>result = sample.map(str -> str.toUpperCase());
	System.out.println(sample.get());
	System.out.println(result.get());
	};
}
```
```
test
TEST
```

####flatMapメソッド
戻り値が新しいOptionalのインスタンスに入れずにそのまま戻します。

```Sample.java
import java.util.Optional;

public class Sample {
	public static void main(String[] args) throws Exception{
		Optional<String>a = Optional.of("test");
		Optional<String>b = a.flatMap(str-> test(str));
		System.out.println(b.get());
	}
	private static Optional<String> test(String str){
		return Optional.of(str.toUpperCase());
	}
}
```
```
TEST
```

####getFormArrayメソッド
配列とインデックス番号を受け取り、配列からインデックス番号に一致する要素を戻します。

####emptyメソッド
arrayの中身がnullであれば空のOptialのインスタンスを生成して、参照を戻します。

####ofNullableメソッド
nullでなければindexに一致する配列の要素を持ったOptioanlのインスタンスを作成し参照を戻します。

```Sample.java
import java.util.Optional;

public class Sample {
	public static void main(String[] args) {
		Optional<String> result =getFromArray(new String[]{"A","B",null},3);
		//結果がない場合
		if(result.isEmpty()) {
			System.out.println("空");
			return;
		}
		//インスタンスから値を受け取る
		System.out.println(result.get());
	}
	private static <T> Optional<T> getFromArray(T[] array, int index){
		if(array == null) {
			//arrayの中身がnullであれば空のOptialのインスタンスを生成して、参照を戻す
			return Optional.empty();
		}
		try {
			//nullでなければindexに一致する配列の要素を持ったOptioanlのインスタンスを作成し参照を戻す
			return Optional.ofNullable(array[index]);
		}catch(ArrayIndexOutOfBoundsException e){
			return Optional.empty();
		}
	}
}
```