LoginSignup
380
315

More than 1 year has passed since last update.

Java7からJava16までの変遷。

Last updated at Posted at 2021-02-05

まえがき

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

Javaの変遷

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

image.png

Java8

2014/03/18 正式リリース(GA)
https://openjdk.java.net/projects/jdk8/

ラムダ式

https://openjdk.java.net/projects/lambda/
https://qiita.com/sano1202/items/64593e8e981e8d6439d3

public static void main(String[] args) {

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

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

StreamAPI

Java Stream APIをいまさら入門 - Qiita
コレクション(から作ったStream)に対して中間処理、終端処理を実行できる。
メソッドチェーンで様々な処理を簡潔に書くことができてよい。

Optional

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

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で済ませることができるように。
メソッドの戻す型を変えたりしたとき、それを受け取る変数の型を変えずに済むのはすごく楽だと思います。

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/

型推論のラムダ式対応

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

HTTP Client

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

// 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文の前にインスタンスを作っておく必要がなくなって幾分かコードをシンプルにできそう。

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/

テキストブロック

【Modern Java】Java15で正式リリースとなったテキストブロック(JEP 378: Text Blocks)

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

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)

// 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で型のチェックと同時に、その型の変数を使えるようにできる。

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

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

(2nd Preview) Sealed Class

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

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


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

380
315
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
380
315