*

java8(JDK8)の新機能をEclipseとJUnitで[インターフェースのデフォルト実装の使い方]

公開日: : 最終更新日:2015/05/02 Java


スポンサードリンク



本エントリーでは、まずSAM Typeの説明をさせていただきます。
その流れの中で「java8の新機能」である「インターフェースのデフォルト実装」の説明をさせていただきます。

「SAM Type」とは

「Single Abstract Method」の省略形です。では関数型インターフェースとの関係は?
と思いますよね、という事で試してみました。

抽象クラスで試してみる。

いきなり結論からですが、厳密には「SAM Type」は関数型インターフェースではないです。
「SAM Type」なインターフェース=関数型インターフェースです。

念のため検証してみました。
抽象クラスで、抽象メソッドを1つしか持たないクラスを作成して、ラムダ式(Lambda Expressions)の左辺に
利用して確認してみました。すると、コンパイルエラーをくらってしまいました。

[その2:関数型インターフェースを例としたラムダ式]
で利用したテストケース

を使って上記の事実を検証するために以下の抽象クラスを作成しました。

作成後にIFuncSampleTestの10行目の
“IFuncSample funcSample =”を
“AbstractFuncSample funcSample =”に
変更してみました。

するとコンパイルエラーが発生しました。
スクリーンショット 2014-04-18 19.48.06

少し小さいので見にくいですね、エラーの核心は、
「The target type of this expression must be a functional interface」
です。

以上の事から、抽象クラスの「SAM Type」は「関数型インターフェース」ではないことが分かりました。
「Single Abstract Method」なインターフェースの方が「関数型インターフェース」よりも
どんなインターフェースか想像しやすいので「SAM Type」がたまに使われるのではないかと考えます。

デフォルト実装を持ったインターフェースで試してみる

JDK8からインターフェースのデフォルト実装が可能となりました。

インターフェースのデフォルト実装と@FunctionalInterfaceの関係を試してみる

インターフェースのメソッドにデフォルト実装がある時に、
そのインターフェースが@FunctionalInterfaceの条件に合致するかを検証してみます。

・「Single Abstract Method」にデフォルト実装をしてみる。

IFuncSampleのhogeメソッドにデフォルト実装をしてみました。
以下は、デフォルト実装前となります。

以下が、デフォルト実装後となります。

デフォルト実装後は、コンパイルエラーが出ます。デフォルト実装すると「SAM Type」と認識されない仕様のようです。
Invalid ‘@FunctionalInterface’ annotation; IFuncSample is not a functional interface

・デフォルト実装をしたメソッドを追加してみる。

次は、hogeメソッドはそのままにし、デフォルト実装をしたhogehogeメソッドを追加してみます。

コンパイルも通りましたし、テストケースも通りました。
スクリーンショット 2014-04-18 21.34.58

この結果から、デフォルト実装したメソッドは「SAM」TypeのSingleには加算されないことが分かりました。

インターフェースのデフォルト実装による弊害

確かに、インターフェースのデフォルト実装が可能になったことによって
独自フレームワークのクラス等を作る時の基底クラスを作る時の手間が省けます。

今までは、インターフェースを実装した抽象クラス等を作成して、
デフォルト実装の処理を実現するとの手法を取る必要がありましたよね。

しかし、この仕様は良い事ばかりではありません。
今までのJavaでは考慮しなくても良かった概念を理解し、それに起因する問題に対処しなければならなくなりました。

インターフェースの実装クラスの実装時

クラスAがインターフェースBとインターフェースCを実装しており
インターフェースBとインターフェースCが同一のメソッド名と引数定義の
デフォルト実装を持ったメソッドを保有している時です。

先ほどのIFuncSampleとhogehogeメソッドが衝突するようにIFuncExampleインターフェースを
作成して、両インターフェースを実装するFuncSampleImplクラスを作成してみました。

IFuncExample.java

FuncSampleImpl.java

するとコンパイルエラーが発生しました。
スクリーンショット 2014-04-18 22.09.52

エラーメッセージの抜粋は以下の通りです。hogehogeが多重定義されていると言われました。
Duplicate default methods named hogehoge with the parameters () and () are inherited from the types IFuncExample and IFuncSample

このエラーを解消するには2つの解決策のどちらかを行う必要があります。

  1. インターフェースのどちらか一方のhogehogeメソッドの引数を変更する。
  2. FuncSampleImplでhogehogeをオーバーライドする。

 

なお、インターフェースのどちらか一方からhogehogeメソッドの
デフォルト実装を除去することでも、本問題を解決できそうな気がしますが、以下のエラーメッセージに変わるだけです。

The default method hogehoge() inherited from IFuncSample conflicts with another method inherited from IFuncExample
今度は衝突していると言われてしまいます。

この状態からでも解決策2を行えばエラーは無くなりますので、
結局実装クラスのhogehogeメソッドの実装が全てを解決してくれます。

インターフェースの多重継承時

IFuncExampleとIFuncSampleを継承するインターフェースIFuncSampleExを作成しました。
(IFuncExampleとIFuncSampleはhogehogeメソッドのデフォルト実装を持っている。)

IFuncSampleEx.java

この状態ではコンパイルエラーの内容は以下の通りです。
FuncSampleImplクラスの初めのエラーと同じです。
Duplicate default methods named hogehoge with the parameters () and () are inherited from the types IFuncExample and IFuncSample

このエラーを解消するには2つの解決策のどちらかを行う必要があります。

  1. インターフェースのどちらか一方のhogehogeメソッドの引数を変更する。
  2. IFuncSampleExでhogehogeををデフォルト実装する。

 

なお、インターフェースのどちらから一方からhogehogeメソッドのデフォルト実装を除去した場合もコンパイルエラーが発生します。
エラーメッセージは、FuncSampleImplクラスと全く同じとなります。

実装クラスまたは継承インターフェースからのデフォルト実装呼び出し

前述のように、せっかくインターフェースのデフォルト実装をしても、多重定義や衝突としてコンパイラが認識してしまい、
オーバーライドしないとコンパイルが通らず、デフォルト実装が使えないとの場面が想定されます。

「Java 8」は、この様な場面も想定しています。

FuncSampleImplクラスを例として説明させていただきます。
と言っても、コメントが全てです。

IFuncSample.super.hogehoge();の呼び出しは、IFuncSampleExからも同じ様に利用可能です。
ちなみにですが、Eclipseのコードアシストでは、IFuncSample.と入力した後でsuperの候補が表示されませんので、手入力する必要があります。

「java8(JDK8)の新機能[インターフェースのデフォルト実装]」は以上です。


スポンサードリンク



関連記事

Spring5入門[STS(Spring Tool Suite)の環境作成と簡単なWebアプリの作成]

Struts1ももう過去の遺物になり、SAStrutsもEOLとなりもう半年以上が経過しました。

記事を読む

Eclipse4.4(Java)におけるビルド・パス関係の設定方法[ビルド・クラスパスの順序およびエクスポート設定]

Eclipse4.4(Java)におけるビルド関係のビルド・パス上の「ビルド・クラスパスの順序および

記事を読む

java8(JDK8)の新機能[大幅に強化されたコレクションAPI:java.util.List] をeclipseとJUnitで確認する。

Java8(JDK8)では、ラムダ式の導入を前提とした、コレクションAPIの新機能が追加されました。

記事を読む

Eclipseのインストールと日本語化とJDK8(Java8)対応[Eclipse4.4とEclipse4.3]

インストールするEclipseのバージョンですが、とりあえず4.3をターゲットとしておき、 4.4

記事を読む

Java超入門 with Eclipse[5:クラスに関する基礎知識(メソッドをJUnitを使って説明)]

クラスに関する基礎知識シリーズも、いよいよメソッドを残すのみとなりました。 前回までは、Eclip

記事を読む

Eclipse4.4(Java)におけるビルド・パス関係の設定方法[ビルド・パス上のソース・フォルダー]

Eclipse4.4(Java)におけるビルド関係のビルド・パス上のソース・フォルダーの利用方法を説

記事を読む

JUnit入門その4[Eclipse4.4のJUnitプラグインとDBUnitの併用(環境構築と基本)]

JUnit入門その1 JUnit入門その2[Eclipse4.4のJUnitプラグインのasse

記事を読む

Selenium入門その5[ページオブジェクトパターン(Page Object Design Pattern)を利用して変更に強いテストを作成する方法]

Selenium入門その2 では「UIマップファイル」と言う仕組みが存在していることに言及させてい

記事を読む

Java8の新機能に完全対応のEclipseメジャーリリースとなる Eclipse 4.4 Luna (ルナ) が遂にリリース

Eclipse メジャーリリースとなる Eclipse 4.4 Luna (ルナ) が遂にリリースさ

記事を読む

Eclipse(4.3,4.4)の使い方[パースペクティブのツールバーのカスタマイズ(「コマンド・グループ可用性」と「ショートカット」タブ)]

「パースペクティブのカスタマイズ」画面には、以下の4つのタブが存在しております。 ツール・バ

記事を読む

Message

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

Spring5入門[STS(Spring Tool Suite)で簡単なWebアプリの典型的なユニットテストの実現方法]

前回は「Spring入門」で、Spring MVCを利用した簡単なWe

Spring5入門[STS(Spring Tool Suite)の環境作成と簡単なWebアプリの作成]

Struts1ももう過去の遺物になり、SAStrutsもEOLとなりも

Selenium入門その6[Selenium3でWebDriver(Java/Junit4)の環境を作成しEdge,Chrome,Firefoxで確認してみる]

Selenium3も3.0.1がリリースされましたし、今後は本格的にS

Selenium利用時のトラブルシューティング方法[クリック編]

Seleniumは便利なテスト自動化ツールですし、今後は更なる利用者の

Java8のラムダ式とStream APIを利用してコーディング量の削減サンプル集

Java8になりラムダ式と「Stream API」が利用できるようにな

→もっと見る

Optimization WordPress Plugins & Solutions by W3 EDGE
PAGE TOP ↑