1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ひとりアドカレ2024 byもんすんAdvent Calendar 2024

Day 3

とあるJavaエンジニアの幻想御手(レベルアッパー) Java8→9編

Posted at

はじめに

こんにちは、もんすんです。

私の実務経験として、最近Javaが一番長くなってきました。
特に保守業務が多いので、Javaのバージョンは最新ではなく、LTSであるJava8を常用しています。

さて、先日JJUG CCC Fall 2024というJavaのカンファレンスに参加してきました。
そのカンファレンスで、とある会社のブースが「Java23クイズ」を出題しており、意気揚々と参加したのですが…悉く間違えてしまいました。

(唯一正解したのは、Effective Java 第2版の表紙の絵柄だけ……)

レベル0扱いされてもおかしくない状況でした。
そこで、大恥をかいた私は思いました。

レベルアップしたい!!と。

Java8は素敵なバージョンで、Lambda式やStream APIといった要素が追加されましたが、それ以降もJavaの進化は止まりません。
未来の現場で時代遅れの開発者とならないためにも、最新の情報を頭に入れ、日々の鍛錬を怠らないようにしたいです。

某ラノベにおける、音声ファイルでの脳波へ干渉云々とかがあれば一瞬で解決するかもしれませんが、現実はそう甘くありません。
地道な努力が必要です。

今回は、Java9をJava8と比較しながら、新しく追加された機能やその活用方法を紹介していきます。
この記事を通じて、だれかの超能力ではなく、技術力を高める助けとなれば幸いです。

※今回の記事は、以下の記事を参考にさせていただきました。

環境

今回、Java8とJava9の環境をそれぞれDockerで構築し、その中で作業をしていきます。
環境差異はありますが、とりあえずJavaが使えればOKと思って使うことにしました。

Java8

FROM amazoncorretto:8u432-al2023-jre

# 作業ディレクトリを設定
WORKDIR /app

# コンテナを常時起動状態にする
CMD ["tail", "-f", "/dev/null"]

Java9

FROM ubuntu:20.04

ENV DEBIAN_FRONTEND=noninteractive

# 必要なツールをインストール
RUN apt-get update && \
  apt-get install -y --no-install-recommends \
  curl \
  unzip \
  && rm -rf /var/lib/apt/lists/*

# Java 9のバイナリをダウンロードしてインストール
RUN curl -k -L -o openjdk9.tar.gz https://download.java.net/java/GA/jdk9/9.0.4/binaries/openjdk-9.0.4_linux-x64_bin.tar.gz && \
  mkdir -p /usr/lib/jvm && \
  tar -xzf openjdk9.tar.gz -C /usr/lib/jvm && \
  rm openjdk9.tar.gz

# Javaの環境変数を設定
ENV JAVA_HOME=/usr/lib/jvm/jdk-9.0.4/
ENV PATH="$JAVA_HOME/bin:${PATH}"

# 作業ディレクトリを設定
WORKDIR /app

# コンテナを常時起動状態にする
CMD ["tail", "-f", "/dev/null"]

Java8からJava9へのレベルアップ!

てれれ、てってって〜ん:musical_note:

1. Jshell

コマンドラインからJavaを実行できるもののようです。
コマンドラインでjshellコマンドを入力するだけで、実行ができます。

Java8では当然存在しない機能なので、以下のようにコマンドを実行しても、command not foundになります。
スクリーンショット 2024-11-06 21.35.06.png

Java9ではどうでしょうか?
このようにコマンドを実行するとjshell >と入力受付待ちの状態になりました。
スクリーンショット 2024-11-06 21.34.48.png

簡単な処理ですが、変数を持たせたり、出力したりできました!
スクリーンショット 2024-11-06 22.03.16.png

終了する際は、

/exit

を実行することで、通常のコマンドラインに戻ることが可能です。

2. 不変なコレクション

外部ライブラリなしで、Java8で、不変なコレクションを作成するには、Collectionsクラスの unmodifiableListなどを利用します。ただ、これは既存のコレクションをラップする方法であり、元のコレクションが変更されると不変性が保たれません。

List<String> mutableList = new ArrayList<>(Arrays.asList("a", "b", "c"));
List<String> immutableList = Collections.unmodifiableList(mutableList);

もしくは、Stream APIを利用して作成することも可能です。

List<String> immutableList = Stream.of("a", "b", "c")
    .collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));

それをJava9では、

List<String> immutableList = List.of("a", "b", "c");

と作成することが可能になっています。
実行してみると、実行時エラーになることも確認できました。
スクリーンショット 2024-11-06 22.42.20.png

どうようにMap/Setも不変にすることができるみたいでした。

3. try-with-resources文の変更

みんな大好きtry-with-resources文ですね。
Java8では、当然以下のように実装しますね。

import java.io.BufferedReader;
import java.io.FileReader;

public class TryWithResources {
  public void useTryWithResources() {
    try (BufferedReader br = new BufferedReader(new FileReader("tryWithResources.txt"))) {
      String line;
      while ((line = br.readLine()) != null) {
        System.out.println(line);
      }
    } catch (Exception e) {
      System.out.println(e.getMessage());
    }
  }
}

Java9では、try節の中でクラスを宣言する必要がなくなりました。

import java.io.BufferedReader;
import java.io.FileReader;

public class TryWithResources {
  public void useTryWithResources() throws Exception {

    // このように実装が可能
    BufferedReader br = new BufferedReader(new FileReader("tryWithResources.txt"));

    try (br) {
      String line;
      while ((line = br.readLine()) != null) {
        System.out.println(line);
      }
    } catch (Exception e) {
      System.out.println(e.getMessage());
    }
  }
}

4. Stream APIの変更

Java9で、Stream APIにtakeWhiledropWhileofNullableメソッドが追加されました。

takeWhileメソッド

先頭から連続して、指定した条件を満たす値を取得するメソッドです。
条件が不一致になるまでの値を全て取得してくれます。

List<Integer> list = List.of(1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1);
list.stream()
    .takeWhile(i -> i < 5)
    .forEach(System.out::println);

/*
* 実行結果:
* 1
* 2
* 3
* 4
*/

上記の例では、先頭から5より小さい数を連続で取得するため、1, 2, 3, 4までが出力されます。リストの5が判定された時点で、それ以降の値は取得されません。
そのため、例えば、上記例におけるリストの先頭が5以上の値の場合、takeWhileが返却するStreamは空になります。

dropWhileメソッド

先頭から連続して、指定した条件を満たす値を除去し、残りを取得するメソッドです。
条件が不一致になった時点以降の値を全て返却します。

List<Integer> list = List.of(1, 2, 3, 4, 5, 5, 4, 3, 2, 1);
list.stream()
    .dropWhile(i -> i < 5)
    .forEach(System.out::println);
/*
* 実行結果:
* 5
* 5
* 4
* 3
* 2
* 1
*/

上記の例では、先頭から5より小さい数を連続でスキップ(除去)するため、初めて5以上の値がチェックされた時点で、それ以降の値が表示されます。

ofNullableメソッド

引数に指定する値がnullでない場合にStreamを返すメソッドです。

List<Integer> list = List.of(1, 2, 3);
Map<Integer, String> map = new HashMap<>() {
  {
    put(1, "one");
    put(2, "two");
    put(4, "four");
  }
};
list.stream()
    .map(map::get)
    .flatMap(Stream::ofNullable)
    .forEach(System.out::println);
/*
* 実行結果:
* one
* two
*/

上記の例では、listに1,2,3が入っており、mapのkeyには、1,2,4が入っている。
もし仮に以下のようにofNullableの処理を記述していない場合、listの3がmapのkeyに存在しないため、nullも返却される。

// 上の例からofNullableの行を削除した場合、
list.stream()
    .map(map::get)
-    .flatMap(Stream::ofNullable)
    .forEach(System.out::println);
/*
* 実行結果:
* one
* two
* null
*/

ofNullableメソッドを利用することで、nullをStreamから弾くことができるということになります。

5. Interface内のprivateメソッド

Java8では、Interfacedefaultメソッドstaticメソッドが定義できるになったらしいです。
defaultメソッドとは、Interfaceにも関わらず、共通処理を定義したときに実装できるメソッドですね。

Java9では、さらにprivateメソッドを実装できるようになりました。

このprivateメソッドは、default/staticメソッドから呼び出すことが可能です。

Java8では正しくエラーになりますね。
スクリーンショット 2024-11-16 22.05.09.png

その他

以下は、詳しく調べてみましたが、あまり自分の中で使い所もなさそうだったので、割愛しました。

  • 匿名クラスでのダイヤモンド演算子
  • リアクティブストリーム
  • Optionalクラスでのメソッドの追加
  • Deprecatedアノテーションの強化
  • モジュールシステム(Project Jigsaw)
  • ... エトセトラエトセトラ

終わりに

Java9の新機能をざっと触れてみましたが、いかがだったでしょうか?
個人的には、不変コレクションの作成が簡単になった点が印象的でした。

現場ではまだJava8を使うことが多いですが、時代の先を行く新しい機能にはやはり惹かれるものがありますね。

次回は、Java9に引き続き、Java10以降の新機能(未元物質)についても触れていこうと思っています。今回同様、実際のコード例を交えながら解説していこうと思います。
一緒にレベルアップを目指しましょう!

1
0
0

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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?