Java7からJava16までの変遷。

# まえがき
ずっとJava11を使っていました。そのためすっかりラムダ式やStreamAPIでの書き方に慣れていたのですが、最近Java7を使って稼働しているプロジェクトに異動したので、何ができて何ができないのか、ちょっと調べてみました。

# Javaの変遷
私見ですが主要だと思う仕様変更を並べてみました。アプリ実装に関係する部分のみピックアップしています。
このバージョンのこれは入れておいたほうが良いよ！との意見がありましたらコメントにぜひお願いします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117369/bc2e7703-2ad1-711f-901f-bfbc2614a4e8.png)

## Java8
2014/03/18 正式リリース(GA)
https://openjdk.java.net/projects/jdk8/
### ラムダ式
https://openjdk.java.net/projects/lambda/
https://qiita.com/sano1202/items/64593e8e981e8d6439d3

```java
public static void main(String[] args) {

  Runnable runner = () -> { System.out.println("Hello Lambda!"); };
  runner.run(); //Hello Lambda!
}
```

無名関数を簡潔に呼び出せる。
StreamAPIと合わせてすごくよく使う。

### StreamAPI
[Java Stream APIをいまさら入門 - Qiita ](https://qiita.com/takumi-n/items/369dd3fcb9ccb8fcfa44)
コレクション(から作ったStream)に対して中間処理、終端処理を実行できる。
メソッドチェーンで様々な処理を簡潔に書くことができてよい。

### Optional
https://docs.oracle.com/javase/jp/8/docs/api/java/util/Optional.html

nullを許容し、nullチェックの仕組みを持ったクラス。

### Date and Time API
https://openjdk.java.net/jeps/150
`DateTimeFormatter`とか`ZonedDateTime`とか、日時を扱うのに便利なクラスがたくさん。

## Java9
2017/09/21 正式リリース(GA)
https://openjdk.java.net/projects/jdk9/

なんとJava8から3年半も経っていたのですね。以降は半年に1回のペースでバージョンアップしているようです。
### モジュール化が可能に
https://openjdk.java.net/jeps/261
[java 9のmodule機能を試してみる - Qiita](https://qiita.com/nmatsui/items/73ad642838631bcdc92e#module-system%E3%81%AB%E3%82%88%E3%82%8B%E8%A7%A3%E6%B1%BA)
### JShellの追加
https://openjdk.java.net/jeps/222
あまりアプリで使わないから上には載せませんでしたが、対話型のJava実行環境JShellが追加されたのはここでした。

```
$>jshell
|  JShellへようこそ -- バージョン15.0.2
|  概要については、次を入力してください: /help intro

jshell> System.out.println("Hello, JShell.");
Hello, JShell.
```

## Java10
2018/03/20 正式リリース(GA)
https://openjdk.java.net/projects/jdk/10/
### varによる型推論
https://openjdk.java.net/jeps/286
右辺から明確に型がわかる場合は型の定義は`var`で済ませることができるように。
メソッドの戻す型を変えたりしたとき、それを受け取る変数の型を変えずに済むのはすごく楽だと思います。

```java
var list = new ArrayList<String>();  // infers ArrayList<String>
var stream = list.stream();          // infers Stream<String>
```

## Java11
2018/09/25 正式リリース(GA)
https://openjdk.java.net/projects/jdk/11/

### 型推論のラムダ式対応
https://openjdk.java.net/jeps/323

```java
(var x, var y) -> x.process(y)
// is equivalent to:
(x, y) -> x.process(y)
```

### HTTP Client
https://openjdk.java.net/jeps/321

HTTP2にも対応したHTTP Client. 
これがあればもう`HttpURLConnection`で頑張らなくてよくなる。


```java
// Sync
   HttpClient client = HttpClient.newBuilder()
        .version(Version.HTTP_1_1)
        .followRedirects(Redirect.NORMAL)
        .connectTimeout(Duration.ofSeconds(20))
        .proxy(ProxySelector.of(new InetSocketAddress("proxy.example.com", 80)))
        .authenticator(Authenticator.getDefault())
        .build();
   HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
   System.out.println(response.statusCode());
   System.out.println(response.body());  
```

## Java14
2020/03/17 正式リリース(GA)
https://openjdk.java.net/projects/jdk/14/
### Switch式
https://openjdk.java.net/jeps/361
Switch文を式として扱えて、戻り値を受け取れる。
Switch文の前にインスタンスを作っておく必要がなくなって幾分かコードをシンプルにできそう。

```java
int numLetters = switch (day) {
    case MONDAY, FRIDAY, SUNDAY -> 6;
    case TUESDAY                -> 7;
    case THURSDAY, SATURDAY     -> 8;
    case WEDNESDAY              -> 9;
};
```


## Java15
2020/09/15 正式リリース(GA)
https://openjdk.java.net/projects/jdk/15/

### テキストブロック
https://openjdk.java.net/jeps/378

[【Modern Java】Java15で正式リリースとなったテキストブロック(JEP 378: Text Blocks)](https://blog1.mammb.com/entry/2020/08/12/000000)

`"""`で囲うことで複数行の文字列を表現できるリテラル。
`"`をエスケープさせることなく扱えたり、インデントをいい感じに扱えたりする。
以下の例ではネストの一番浅いところを基準として、インデントを保持してくれる。

```java
HTML example
Using "one-dimensional" string literals

String html = "<html>\n" +
              "    <body>\n" +
              "        <p>Hello, world</p>\n" +
              "    </body>\n" +
              "</html>\n";
Using a "two-dimensional" block of text

String html = """
              <html>
                  <body>
                      <p>Hello, world</p>
                  </body>
              </html>
              """;
```

## Java16
2021/03/16 正式リリース(GA)予定
https://openjdk.java.net/projects/jdk/16/
### Records
https://openjdk.java.net/jeps/395
[レコード（Java14プレビュー版）メモ(Hishidama's record Java14 preview Memo) ](https://www.ne.jp/asahi/hishidama/home/tech/java/preview/record.14.html)

```java
// as-is
public final class Point {
	private final int x;
	private final int y;
	public Point(int x, int y) {
		this.x = x;
		this.y = y;
	}
	public int x() {
		return this.x;
	}
	public int y() {
		return this.y;
	}
	@Override
	public int hashCode() {
		～
	} 
	@Override
	public boolean equals(Object other) {
		～
	} 
	@Override
	public String toString() {
		return "Point[x=" + this.x + ", y=" + this.y + "]";
	}
}
// to-be
public record Point(int x, int y) { } // 簡潔に定義できる
```


### instanceOfパターンマッチング
https://openjdk.java.net/jeps/394
`instanceOf`で型のチェックと同時に、その型の変数を使えるようにできる。

```java
// as-is
if (obj instanceof String) {
  String s = (String)obj;
  ...
}

// to-be
if (obj instanceof String s) {
    // sがStringとして扱える
    ...
}
```

### (2nd Preview) Sealed Class
https://openjdk.java.net/jeps/397

まだJava16時点では正式版となりませんが、シールクラスも追加される予定。
このまま順当にいけばJava17でGAでしょうか。

継承可能なサブクラスを絞る機能で、
クラスやインターフェースの頭に`sealed`とつけ、permitsの後に継承・実装を許可するクラスを指定可能。

```java

sealed interface Shape
    permits Circle, Rectangle { ... }
```
上記例だと`Circle` `Rectangle`以外は`Shape`インターフェースを実装できません。
クラス設計における使いどころ・考え方は以下の記事がよいです。
https://www.infoq.com/jp/articles/java-sealed-classes/

### 
# あとがき
こうして並べてみるとJava8でいかに大きく変わったかわかります。
Java11のHTTP周りのクラス追加と、型推論もかなり大きいと思っています。

### おまけ
ほぼ同じ内容を勉強会で話したので、そのPDF資料も載せておきます。DLはご自由にどうぞ。
https://speakerdeck.com/sivertigo/javaharegasiyan-yu-karamodannayan-yu-he-dokomadezhi-tuteru-javazui-xin-shi-qing