Java 8の新機能
1概要
この記事では、Java 8の最も興味深い新機能について簡単に説明します。
ここでは、インターフェイスのデフォルトメソッドと静的メソッド、メソッド参照、およびOptionalについて説明します。
Java 8のリリースのいくつかの機能 –
ストリームAPI
、
lambda式と関数型インターフェース
– について別の外観に値する包括的なトピックです。
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
キーワード
を使って宣言されます。これらは実装クラスのインスタンスを通してアクセス可能で、オーバーライドすることができます。
Vehicle
インターフェースに
default
メソッドを追加しましょう。これにより、このインターフェースの
static
メソッドも呼び出されます。
default String getOverview() {
return "ATV made by " + producer();
}
このインタフェースが__VehicleImplクラスによって実装されていると仮定します。
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));
filter()
メソッドのラムダ式をよく見てください。これは
User
クラスの静的メソッド
isRealUser(User user)
を呼び出すだけです。そのため、静的メソッドへの参照で置き換えることができます。
boolean isReal = list.stream().anyMatch(User::isRealUser);
この種のコードは、はるかに有益に見えます。
3.2. インスタンスメソッドへの参照
インスタンスメソッドへの参照は、次の構文を保持します。
-
c
__ontainingInstance :: methodName .
** 次のコードは、入力パラメータを検証する
User
型のメソッド
isLegalName(String string)__を呼び出します。
User user = new User();
boolean isLegalName = list.stream().anyMatch(user::isLegalName);
3.3. 特定の種類のオブジェクトのインスタンスメソッドへの参照
この参照メソッドは次の構文を取ります。
-
C
_ontainingType :: methodName .
_
** 例::
long count = list.stream().filter(String::isEmpty).count();
3.4. コンストラクタへの参照
コンストラクターへの参照は次の構文を取ります。
-
ClassName
_ :: new .
Javaのコンストラクタは特別なメソッドなので、メソッド名
.
として
new_
** を利用してメソッド参照を適用することもできます。
Stream<User> stream = list.stream().map(User::new);
4.
オプションの<T>
Java 8以前は、
NullPointerException(NPE)
がスローされる可能性があるため、開発者は参照した値を慎重に検証する必要がありました。これらすべてのチェックは、かなり厄介でエラーを起こしやすい定型コードを要求しました。
Java 8
Optional <T>
クラスは、
NPEを取得する可能性がある状況を処理するのに役立ちます。
T型のオブジェクトのコンテナとして機能します。
null
。このコンテナ内の値が
null
の場合、__NPEをスローするのではなく、定義済みのアクションを実行できます。
4.1.
Optional <T>
の作成
Optional
クラスのインスタンスは、その静的メソッドを使用して作成できます。
Optional<String> optional = Optional.empty();
空の__Optionalを返します。
String str = "value";
Optional<String> optional = Optional.of(str);
null以外の値を含む
Optional
を返します。
Optional<String> optional = Optional.ofNullable(getString());
特定の値で
Optional
を返すか、パラメータが
nullの場合は空の
Optional__を返します。
4.2.
オプション<T>
使用法
たとえば、
List <String>
を取得し、
null
の場合は、それを__ArrayList <String>の新しいインスタンスに置き換えたいと思います。
List<String> list = getList();
List<String> listOpt = list != null ? list : new ArrayList<>();
Java 8では、はるかに短いコードで同じ機能を実現できます。
List<String> listOpt = getList().orElseGet(() -> new ArrayList<>());
古い方法でオブジェクトのフィールドに到達する必要がある場合は、さらに定型コードがあります。
Address
型のフィールドと
String型のフィールドs
treet
を持つ
User
型のオブジェクトがあるとします。何らかの理由で
street
フィールドの値を返す必要があるか、
street
が
null__の場合はデフォルト値を返す必要があります。
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> user = Optional.ofNullable(getUser());
String result = user
.map(User::getAddress)
.map(Address::getStreet)
.orElse("not specified");
この例では、
map()
メソッドを使用して、
getAdress()
の呼び出し結果を
Optional <Address>
に、
getStreet()
を
Optional <String>に変換しています。 )
メソッドは空の
Optional.
を返します。
私たちのゲッターが
Optional <T>を返すことを想像してください。それで、
map()の代わりに
flatMap()
メソッドを使うべきです:__
Optional<OptionalUser> optionalUser = Optional.ofNullable(getOptionalUser());
String result = optionalUser
.flatMap(OptionalUser::getAddress)
.flatMap(OptionalAddress::getStreet)
.orElse("not specified");
Optional
の別のユースケースは、別の例外を除いて
NPE
を変更することです。
それで、以前と同じように、これをJava 8以前のスタイルで試してみましょう。
String value = null;
String result = "";
try {
result = value.toUpperCase();
} catch (NullPointerException exception) {
throw new CustomException();
}
また、
Optional <String>
を使用した場合はどうなりますか?答えはもっと読みやすくそしてより簡単です:
String value = null;
Optional<String> valueOpt = Optional.ofNullable(value);
String result = valueOpt.orElseThrow(CustomException::new).toUpperCase();
アプリで
Optional
をどのようにどのような目的で使用するかは、重大で物議を醸す設計上の決定であり、そのすべての長所と短所の説明はこの記事の範囲外です。あなたが興味を持っているなら、あなたはより深く掘り下げることができます、この問題に捧げられたインターネット上のたくさんの興味深い記事があります。
This one
およびhttp://blog.joda.org/2015/08/java-se-8- optional-pragmatic-approach.html[このもう1つ]は非常に役に立ちます。
5結論
この記事では、Java 8の興味深い新機能について簡単に説明します。
他の多くの追加や改良がもちろんあり、それらは多くのJava 8 JDKパッケージやクラスに広がっています。
しかし、この記事に示されている情報は、これらの新機能のいくつかを調べて学ぶための良い出発点です。
最後に、記事のすべてのソースコードが利用可能です
over on
GitHub。