Java 8の新機能

Java 8の新機能

1. 概要

この記事では、Java8の最も興味深い新機能のいくつかを簡単に見ていきます。

ここでは、インターフェイスのデフォルトメソッドと静的メソッド、メソッド参照、およびオプションについて説明します。

Java 8のリリースのいくつかの機能(stream APIlambda expressions and functional interfaces)は、個別に検討する価値のある包括的なトピックであるため、すでに説明しました。

2. インターフェイスのデフォルトメソッドと静的メソッド

Java 8より前は、インターフェイスにはパブリック抽象メソッドしかありませんでした。 すべての実装クラスに新しいメソッドの実装を強制することなく、既存のインターフェイスに新しい機能を追加することはできませんでした。また、実装でインターフェイスメソッドを作成することもできませんでした。

Java 8以降、インターフェイスにはstaticメソッドとdefaultメソッドを含めることができます。これらのメソッドは、インターフェイスで宣言されているにもかかわらず、動作が定義されています。

2.1. 静的メソッド

次のインターフェイスのメソッドを検討してください(このインターフェイスをVehicleと呼びましょう)。

static String producer() {
    return "N&F Vehicles";
}

静的producer()メソッドは、インターフェースを介して、およびインターフェース内でのみ使用できます。 実装クラスによってオーバーライドすることはできません。

インターフェイスの外部で呼び出すには、静的メソッド呼び出しの標準的なアプローチを使用する必要があります。

String producer = Vehicle.producer();

2.2. デフォルトのメソッド

デフォルトのメソッドは、新しいdefault keywordを使用して宣言されます。 これらは、実装クラスのインスタンスを介してアクセス可能であり、オーバーライドできます。

defaultメソッドをVehicleインターフェースに追加しましょう。これにより、このインターフェースのstaticメソッドも呼び出されます。

default String getOverview() {
    return "ATV made by " + producer();
}

このインターフェイスがクラスVehicleImpl.によって実装されていると仮定します。defaultメソッドを実行するには、このクラスのインスタンスを作成する必要があります。

Vehicle vehicle = new VehicleImpl();
String overview = vehicle.getOverview();

3. メソッド参照

メソッド参照は、既存のメソッドのみを呼び出すラムダ式の短くて読みやすい代替手段として使用できます。 メソッド参照には4つのバリアントがあります。

3.1. 静的メソッドへの参照

静的メソッドへの参照は、次の構文を保持します:ContainingClass::methodName.

Stream APIを使用して、List<String>内のすべての空の文字列をカウントしてみましょう。

boolean isReal = list.stream().anyMatch(u -> User.isRealUser(u));

anyMatch()メソッドのラムダ式を詳しく見てみましょう。Userクラスの静的メソッドisRealUser(User user)を呼び出すだけです。 そのため、静的メソッドへの参照に置き換えることができます。

boolean isReal = list.stream().anyMatch(User::isRealUser);

このタイプのコードは、はるかに有益です。

3.2. インスタンスメソッドへの参照

インスタンスメソッドへの参照は、次の構文を保持します。containingInstance::methodName.次のコードは、入力パラメータを検証するタイプUserのメソッドisLegalName(String string)を呼び出します。

User user = new User();
boolean isLegalName = list.stream().anyMatch(user::isLegalName);

3.3. 特定のタイプのオブジェクトのインスタンスメソッドへの参照

この参照メソッドは、次の構文を取ります。ContainingType::methodName.
long count = list.stream().filter(String::isEmpty).count();

3.4. コンストラクターへの参照

コンストラクターへの参照は次の構文を取ります。ClassName::new. Javaのコンストラクターは特別なメソッドであるため、メソッド名.としてnewを使用すると、メソッド参照も適用できます。

Stream stream = list.stream().map(User::new);

4. オプション

Java 8の開発者は、NullPointerException (NPE)をスローする可能性があるため、参照する値を注意深く検証する必要がありました。 これらすべてのチェックには、かなり面倒でエラーが発生しやすい定型コードが必要でした。

Java 8Optional<T>クラスは、NPE.を取得する可能性がある状況の処理に役立ちます。タイプT.のオブジェクトのコンテナとして機能します。次の場合にこのオブジェクトの値を返すことができます。この値はnullではありません。 このコンテナ内の値がnullの場合、NPE.をスローする代わりに、事前定義されたアクションを実行できます。

4.1. Optional<T>の作成

Optionalクラスのインスタンスは、静的メソッドを使用して作成できます。

Optional optional = Optional.empty();

空のOptional.を返します

String str = "value";
Optional optional = Optional.of(str);

null以外の値を含むOptionalを返します。

Optional optional = Optional.ofNullable(getString());

パラメータがnull.の場合、特定の値を持つOptionalまたは空のOptionalを返します

4.2. Optional<T> usage

たとえば、List<String>を取得することを期待しており、nullの場合は、ArrayList<String>.WithのJava8以前のコードの新しいインスタンスに置き換えます。このようなことをする必要があります:

List list = getList();
List listOpt = list != null ? list : new ArrayList<>();

Java 8では、はるかに短いコードで同じ機能を実現できます。

List listOpt = getList().orElseGet(() -> new ArrayList<>());

古い方法でオブジェクトのフィールドに到達する必要がある場合は、さらに多くの定型コードがあります。 タイプAddressのフィールドとタイプString.のフィールドstreetを持つタイプUserのオブジェクトがあり、何らかの理由で次の値を返す必要があるとします。存在する場合はstreetフィールド、streetnullの場合はデフォルト値:

User user = getUser();
if (user != null) {
    Address address = user.getAddress();
    if (address != null) {
        String street = address.getStreet();
        if (street != null) {
            return street;
        }
    }
}
return "not specified";

これはOptional:で簡略化できます

Optional user = Optional.ofNullable(getUser());
String result = user
  .map(User::getAddress)
  .map(Address::getStreet)
  .orElse("not specified");

この例では、map()メソッドを使用して、getAdress()を呼び出した結果をOptional<Address>に変換し、getStreet()Optional<String>.に変換しました。これらのメソッドのいずれかがnullmap()メソッドは空のOptional.を返します

ゲッターがOptional<T>.を返すと想像してください。したがって、map():の代わりにflatMap()メソッドを使用する必要があります。

Optional optionalUser = Optional.ofNullable(getOptionalUser());
String result = optionalUser
  .flatMap(OptionalUser::getAddress)
  .flatMap(OptionalAddress::getStreet)
  .orElse("not specified");

Optionalの別の使用例は、別の例外を除いてNPEを変更することです。 したがって、以前に行ったように、Java8より前のスタイルでこれを実行してみましょう。

String value = null;
String result = "";
try {
    result = value.toUpperCase();
} catch (NullPointerException exception) {
    throw new CustomException();
}

そして、Optional<String>を使用するとどうなりますか? 答えはより読みやすく簡単です。

String value = null;
Optional valueOpt = Optional.ofNullable(value);
String result = valueOpt.orElseThrow(CustomException::new).toUpperCase();

アプリでOptionalをどのように、どのような目的で使用するかは、深刻で物議を醸す設​​計上の決定であり、そのすべての長所と短所の説明はこの記事の範囲外であることに注意してください。 興味があれば、もっと深く掘り下げることができます。インターネットにはこの問題に関する多くの興味深い記事があります。 This onethis another oneは非常に役立ちます。

5. 結論

この記事では、Java 8の興味深い新機能について簡単に説明します。

もちろん、他にも多くの追加や改善があり、それらは多くのJava 8 JDKパッケージとクラスに広がっています。

しかし、この記事で説明されている情報は、これらの新機能のいくつかを探索して学ぶための良い出発点です。

最後に、記事のすべてのソースコードが利用可能ですover on GitHub.