interface enhancements java 8 java functional interface
このチュートリアルでは、Java 8でのインターフェースへの追加と、抽象クラス、extendsキーワードなどのJavaの概念とインターフェースの違いについて説明します。
私たちはすべてについて探求しました Javaのインターフェース 前回のチュートリアルで。複数のインターフェースを含むJavaのインターフェースの基本概念を紹介し、カバーしました。
Java 8より前は、インターフェースは抽象メソッドと静的変数および最終変数のみを持つことが許可されていました。抽象メソッドはデフォルトでパブリックであり、インターフェースを実装するクラスによってオーバーライドされる必要があります。
したがって、インターフェースは主にコントラクトであり、定数(静的および最終)と抽象メソッドにのみ関係していました。
学習内容:
Java8でのインターフェースの変更
Java 8リリースでは、インターフェースに静的メソッドとデフォルトメソッドが導入または許可されています。開発者は、インターフェイスでデフォルトのメソッドを使用して、インターフェイスにメソッドを追加できます。このようにして、インターフェースを実装するクラスを妨害したり変更したりすることはありません。
Java 8では、インターフェースに静的メソッドを含めることもできます。静的メソッドは、クラスで定義するものと同じです。静的メソッドは、インターフェースを実装するクラスによってオーバーライドできないことに注意してください。
インターフェイスに静的メソッドとデフォルトメソッドが導入されたことで、問題なくインターフェイスを簡単に変更できるようになり、インターフェイスの実装も簡単になりました。
Java 8では、関数型インターフェース内に「ラムダ式」も導入されています。さらに、Java 8以降、Javaにはさらに多くの組み込み関数型インターフェースが追加されています。
このチュートリアルでは、Java 8のインターフェースへのこれらすべての追加について説明し、抽象クラス、extendsキーワードなどのさまざまなJavaの概念とインターフェースの違いについても説明します。
あなたのチューブビデオをダウンロードするためのソフトウェア
Javaのインターフェイスの静的メソッド
インターフェイスには、定義を持つことができるメソッドを含めることもできます。これらは、インターフェースの静的メソッドです。静的メソッドはインターフェース内で定義され、このインターフェースを実装するクラスによってオーバーライドまたは変更することはできません。
これらの静的メソッドは、インターフェイス名を直接使用して呼び出すことができます。
次の例は、静的メソッドの使用法を示しています。
//interface declaration interface TestInterface { // static method definition static void static_print() { System.out.println('TestInterface::static_print ()'); } // abstract method declaration void nonStaticMethod(String str); } // Interface implementation class TestClass implements TestInterface { // Override interface method @Override public void nonStaticMethod(String str) { System.out.println(str); } } public class Main{ public static void main(String() args) { TestClass classDemo = new TestClass(); // Call static method from interface TestInterface.static_print(); // Call overridden method using class object classDemo.nonStaticMethod('TestClass::nonStaticMethod ()'); } }
出力:
上記のプログラムにはTestInterfaceがあります。 「static_print」という名前の静的メソッドと、nonstaticmethodという名前の非静的メソッドがあります。
TestClassにTestInterfaceを実装し、nonStaticMethodをオーバーライドしました。次に、mainメソッドで、TestInterfaceを使用してstatic_printメソッドを直接呼び出し、TestClassのオブジェクトを使用してnonStaticMethodを呼び出します。
インターフェイスのデフォルトメソッド
すでに述べたように、Java8より前のインターフェースは抽象メソッドのみを許可していました。次に、このメソッドの実装を別のクラスで提供します。インターフェイスに新しいメソッドを追加する必要がある場合は、同じクラスでその実装コードを提供する必要があります。
したがって、メソッドを追加してインターフェイスを変更すると、実装クラスも変更されます。
この制限は、インターフェースにデフォルトのメソッドを持たせることができるJava8バージョンによって克服されました。ある意味でデフォルトのメソッドは既存のインターフェースに下位互換性を提供し、実装クラスを変更する必要はありません。デフォルトのメソッドは、「仮想拡張メソッド」または「ディフェンダーメソッド」とも呼ばれます。
デフォルトのメソッドは、宣言でキーワード「default」を使用して宣言されます。宣言の後にメソッドの定義が続きます。インターフェイスを実装するクラスで使用できるデフォルトのメソッドをオーバーライドできます。
同様に、インターフェイスから実装クラスオブジェクトを使用して、オーバーライドせずに直接呼び出すことができます。
interface TestInterface { // abstract method public void cubeNumber(int num); // default method default void print() { System.out.println('TestInterface :: Default method'); } } class TestClass implements TestInterface { // override cubeNumber method public void cubeNumber(int num) { System.out.println('Cube of given number ' + num+ ':' + num*num*num); } } class Main{ public static void main(String args()) { TestClass obj = new TestClass(); obj.cubeNumber(5); // call default method print using class object obj.print(); } }
出力:
上記のJavaプログラムは、インターフェースのデフォルトのメソッドを示しています。 mainメソッドでは、クラスオブジェクトを使用してインターフェイスのデフォルトメソッドを呼び出すことができることに注意してください。これは、クラスがインターフェイスを実装するときに、デフォルトのメソッドがクラスでも使用できるためです。
注意: 実装クラスでもprint()メソッドをオーバーライドすることができます。オーバーライドすると、デフォルトメソッドのアクセス修飾子が実装クラスでpublicに変更されることに注意してください。
デフォルトのメソッドと多重継承
複数のインターフェイスの場合、各インターフェイスに同じプロトタイプのデフォルトメソッドがある場合があります。このような場合、コンパイラはどのメソッドを呼び出すかを知りません。
デフォルトのメソッドがすべてのインターフェイスで同じプロトタイプを持つこの状況が発生した場合、解決策は、実装クラスオブジェクトがデフォルトのメソッドを呼び出すときに、コンパイラがクラスに実装されたメソッドを呼び出すように、実装クラスのメソッドをオーバーライドすることです。 。
次のJavaプログラムは、複数のインターフェースでのデフォルトのメソッドの使用を示しています。
//Interface_One interface Interface_One{ //defaultMethod default void defaultMethod(){ System.out.println('Interface_One::defaultMethod'); } } //Interface_Two interface Interface_Two{ //defaultMethod default void defaultMethod(){ System.out.println('Interface_Two::defaultMethod'); } } class TestExample implements Interface_One, Interface_Two{ public void disp(String str){ System.out.println('String is: '+str); } //override defaultMethod to take care of the ambiguity public void defaultMethod(){ System.out.println('TestExample::defaultMethod'); } } class Main{ public static void main(String() args) { TestExample obj = new TestExample(); //call the default method obj.defaultMethod(); } }
出力:
上記のプログラムでは、実装クラスのデフォルトのメソッド(両方のインターフェイスで同じプロトタイプを持つ)をオーバーライドしました。このように、実装クラスのオブジェクトを使用してmainメソッドからdefaultメソッドを呼び出すと、オーバーライドされたメソッドが呼び出されます。
Java8機能インターフェース
関数型インターフェースは、抽象メソッドが1つしかないインターフェースです。デフォルトメソッドと静的メソッドをいくつでも含めることができますが、含まれる抽象メソッドは1つだけです。さらに、機能インターフェイスには、オブジェクトクラスメソッドの宣言を含めることができます。
機能インターフェースは「 単一の抽象メソッドインターフェイス 」または「 SAMインターフェース 」。 SAMインターフェースはJavaの新機能です。
Javaプログラムでは、関数型インターフェースの存在は、 @FunctionalInterface 注釈。コンパイラーがこの注釈に遭遇すると、この注釈に続くインターフェースが機能していることがわかります。したがって、複数の抽象メソッドが含まれている場合は、エラーが点滅します。
注釈 @FunctionalInterface ただし、Javaでは必須ではありません。
次のプログラムは、Javaの関数型インターフェースを示しています。
//declare a functional interface @FunctionalInterface //annotation indicates it’s a functional interface interface function_Interface{ void disp_msg(String msg); // abstract method // Object class methods. int hashCode(); String toString(); boolean equals(Object obj); } //implementation of Functional Interface class FunctionalInterfaceExample implements function_Interface{ public void disp_msg(String msg){ System.out.println(msg); } } class Main{ public static void main(String() args) { //create object of implementation class and call method FunctionalInterfaceExample finte = new FunctionalInterfaceExample(); finte.disp_msg('Hello, World!!!'); } }
出力:
上記のプログラムの関数型インターフェースには、単一の抽象メソッドがあり、hashCode、toString、equalsなどのオブジェクトクラスメソッド宣言もあります。このインターフェースを実装するクラスでは、抽象メソッドがオーバーライドされます。 mainメソッドでは、実装クラスのオブジェクトを作成し、そのメソッドを使用します。
RunnableやComparableなどのインターフェースは、Javaで提供される機能インターフェースの例です。 Java 8では、ラムダ式を関数型インターフェースオブジェクトに割り当てることができます。
次のサンプルプログラムはこれを示しています。
class Main{ public static void main(String args()) { // use lambda expression to create the object new Thread(()-> {System.out.println('New thread created with functional interface');}).start(); } }
出力:
Java 8は、java.util.functionパッケージで多くの組み込み関数型インターフェースも提供します。
これらの組み込みインターフェースについて、以下で説明します。
#1)述語
これは、単一の抽象メソッドテストを持つJavaの関数型インターフェースです。 「test」メソッドは、指定された引数をテストした後、ブール値を返します。
以下に示すのは、述語インターフェースのテストメソッドのプロトタイプです。
C ++でのクイックソート
public interface Predicate { public boolean test(T t); }
#2)BinaryOperator
BinaryOperatorインターフェースは、2つの引数を受け入れ、引数と同じタイプの結果値を返す抽象メソッド「apply」を提供します。
acceptメソッドのプロトタイプは次のとおりです。
public interface BinaryOperator { public T apply (T x, T y); }
#3)機能
関数型インターフェースは、「apply」という名前の抽象メソッドも備えた関数型インターフェースです。ただし、このapplyメソッドは、タイプTの単一の引数を取り、タイプRの値を返します。
applyメソッドのプロトタイプは次のとおりです。
public interface Function { public R apply(T t); }
次のJavaプログラムは、上記の組み込み関数型インターフェース述語を示しています。
import java.util.*; import java.util.function.Predicate; class Main { public static void main(String args()) { // create a list of strings List names = Arrays.asList('Karen','Mia','Sydney','Lacey','Megan'); // declare string type predicate and use lambda expression to create object Predicate p = (s)->s.startsWith('M'); System.out.println('Names starting with M:'); // Iterate through the list for (String st:names) { // test each entry with predicate if (p.test(st)) System.out.println(st); } } }
出力:
上記のプログラムでわかるように、文字列のリストがあります。関数型インターフェースの述語を使用して、文字列内の項目がMで始まるかどうかをテストし、始まる場合は名前を出力します。
Javaのクラス対インターフェイス
クラスとインターフェイスは構文が似ているため似ていますが、これら2つのエンティティには類似点よりも多くの違いがあります。
Javaのクラスとインターフェースの違いをいくつか挙げてみましょう。
クラス | インターフェース |
---|---|
クラスからオブジェクトをインスタンス化して作成できます。 | インターフェイスをインスタンス化できません。 |
キーワード「class」は、クラスを作成するために使用されます。 | インターフェイスは、キーワード「interface」を使用して作成されます。 |
クラスは、Javaでの多重継承をサポートしていません。 | インターフェイスはJavaで多重継承をサポートします。 |
クラスにはコンストラクターが含まれています。 | インターフェイスにはコンストラクタが含まれていません。 |
クラスに抽象メソッドを含めることはできません。 | インターフェイスには抽象メソッドのみが含まれています。 |
クラスには、デフォルト、パブリック、プライベート、または保護された変数とメソッドを含めることができます。 | インターフェイスには、デフォルトでパブリック変数とメソッドのみがあります。 |
非アクセス修飾子をクラスの変数に関連付けることは必須ではありません。 | インターフェイスには、静的または最終的な変数を含めることができます。 |
クラスから別のクラスを継承できます。 | インターフェイスからクラスを継承することはできません。 |
クラスは、キーワード「extends」を使用して継承できます。 | このインターフェースは、「implements」キーワードを使用して別のクラスで実装できます。 「extends」キーワードを使用して、別のインターフェースに継承できます。 |
Javaは実装に対して拡張します
「拡張する」 | 「実装」 |
---|---|
インターフェイスは、静的および最終的な非アクセス修飾子のみをサポートします。 | Abstractは、static、final、non-static、non-finalなどのすべての非アクセス修飾子をサポートします。 |
クラスは「extends」キーワードを使用して別のクラスから継承します。 | 「implements」キーワードは、インターフェースを実装するためにクラスによって使用されます。 |
別のクラスを継承するクラスは、親クラスのすべてのメソッドをオーバーライドする場合としない場合があります。 | インターフェイスを実装するクラスは、インターフェイスのすべての抽象メソッドをオーバーライドする必要があります。 |
extendsキーワードを使用して、一度に1つのクラスのみを拡張できます。 | 「implements」キーワードを使用して、複数のインターフェースを実装できます。 |
インターフェイスは、「extends」キーワードを使用して別のインターフェイスを拡張できます。 | インターフェイスは、「implements」キーワードを使用して別のインターフェイスを実装することはできません。 |
抽象クラスはJavaでインターフェイスを実装できますか
はい、抽象クラスは「implements」キーワードを使用してインターフェースを実装できます。抽象クラスは、すべてのインターフェイス抽象メソッドを実装する必要はありません。ただし、全体として、すべての抽象メソッドとのインターフェイス、このインターフェイスを実装する抽象クラス、そして具体的なクラスを用意することをお勧めします。
以下に示すのは、Javaでのそのような実装の例です。
ここで、java.util.Listはインターフェースです。このインターフェースは、java.util.AbstractListによって実装されます。次に、このAbstractListクラスは、LinkedListとArrayListという2つの具象クラスによって拡張されます。
LinkedListクラスとArrayListクラスがListインターフェイスを直接実装している場合は、Listインターフェイスのすべての抽象メソッドを実装する必要があります。
ただし、この場合、AbstractListクラスはListインターフェイスのメソッドを実装し、それらをLinkedListとArrayListに渡します。したがって、ここでは、インターフェイスから型を宣言するという利点と、共通の動作を実装する抽象クラスの柔軟性を利用できます。
Javaで抽象クラスとインターフェイスを使用する場合
主に抽象クラスを使用して、この抽象クラスから拡張される子クラスのデフォルトまたは共通の動作を定義します。インターフェイスは、アプリケーションで相互作用する2つのシステム間のコントラクトを定義するために使用されます。
特定の状況は、使用するインターフェースや、抽象クラスを使用してのみ解決できる特定の問題にとって理想的です。このセクションでは、インターフェイスを使用できる場合と抽象クラスを使用できる場合について説明します。
インターフェイスを使用する場合:
- インターフェースは主に、実装する小さな簡潔な機能がある場合に使用されます。
- APIを実装していて、しばらくの間APIが変更されないことがわかっている場合は、そのときにインターフェースを使用します。
- インターフェイスを使用すると、多重継承を実装できます。したがって、アプリケーションに多重継承を実装する必要がある場合は、インターフェイスを使用します。
- オブジェクトの範囲が広い場合も、インターフェイスの方が適しています。
- また、多くの無関係なクラスに共通の機能を提供する必要がある場合でも、インターフェースが使用されます。
抽象クラスを使用する場合:
- 抽象クラスは主に、アプリケーションで継承を使用する必要がある場合に使用されます。
- インターフェイスはパブリックメソッドと変数を処理するため、プログラムで非パブリックアクセス修飾子を使用する場合は常に、抽象クラスを使用します。
- 新しいメソッドを追加する必要がある場合は、インターフェイスよりも抽象クラスで追加することをお勧めします。インターフェイスに新しいメソッドを追加すると、インターフェイスにはメソッドプロトタイプしかなく、インターフェイスを使用したクラス実装が実装を提供するため、実装全体が変更されるためです。
- 開発中のコンポーネントの異なるバージョンが必要な場合は、抽象クラスを選択します。抽象クラスをより簡単に変更できます。ただし、インターフェースは変更できません。新しいバージョンが必要な場合は、インターフェイス全体を再度作成する必要があります。
- すべてのコンポーネントに共通の実装を提供する場合は、抽象クラスが最適です。
Javaでのインターフェイスと抽象クラス
以下に示すのは、JavaのInterfacesクラスとAbstractクラスの違いの一部です。
インターフェース | 抽象クラス |
---|---|
インターフェイスは、「interface」キーワードを使用して宣言されます。 | 抽象クラスは、「abstract」キーワードを使用して宣言されます。 |
インターフェイスは、「implements」キーワードを使用して実装できます。 | 要約は、「extends」キーワードを使用して継承できます。 |
インターフェイスは、クラスを拡張したり、インターフェイスを実装したりすることはできません。別のインターフェイスのみを拡張できます。 | 抽象クラスは、クラスを拡張したり、複数のインターフェースを実装したりできます。 |
インターフェイスメンバーはパブリックにすることしかできません。 | 抽象クラスのメンバーは、パブリック、プライベート、または保護することができます。 |
インターフェースを使用して実装を提供することはできません。宣言としてのみ使用できます。 | 抽象クラスは、インターフェースの実装に使用できます。 |
多重継承は、インターフェースを使用して実現できます。 | 抽象クラスは多重継承をサポートしていません。 |
インターフェイスは抽象メソッドのみを持つことができます。 Java 8からは、静的メソッドとデフォルトメソッドを持つことができます。 | 抽象クラスは、抽象メソッドまたは非抽象メソッドを持つことができます。 |
Javaでの列挙型継承
Javaのデータ型に関する説明では、列挙型のデータ型について説明しました。すべての列挙型はjava.lang.Enumクラスから拡張されます。このクラスjava.lang.Enumは抽象クラスです。
また、Javaのすべての列挙型クラスはデフォルトで「最終」です。したがって、列挙型クラスからクラスを継承しようとすると、コンパイラエラーが発生します。
Javaは多重継承を許可していないため、enumクラスはすでにjava.lang.Enumから継承しているため、他のクラスからenumクラスを継承することはできません。ただし、列挙型クラスはJavaでインターフェイスを実装でき、これはJavaでは列挙型継承と呼ばれます。
以下に示すのは、Javaでの列挙型継承の例です。
//WeekDays interface declaration interface WeekDays { public void displaydays(); } //enum class implementing WeekDays interface enum Days implements WeekDays { SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY,FRIDAY, SATURDAY; public void displaydays() { //Override displaydays method System.out.println('The day of the week: ' + this); } } class Main { public static void main(String() args) { Days.MONDAY.displaydays(); //access enum value } }
出力:
ここに、抽象メソッドプロトタイプdisplaydays()を持つインターフェイスWeekDaysがあります。次に、WeekDaysインターフェイスを実装する列挙型クラスDaysを定義します。ここでは、SUNDAYからSATURDAYまでの列挙値を定義し、displaydaysメソッドもオーバーライドします。
最後に、mainメソッドで、列挙値にアクセスして表示します。
よくある質問
Q#1)インターフェースでメソッド本体を指定するとどうなりますか?
回答: Java 8より前のバージョンのJavaの場合、メソッドの本体はインターフェースで許可されていません。ただし、Java 8以降、インターフェイス内でデフォルトメソッドまたは静的メソッドを定義できます。
Q#2)Java 8でインターフェースに変数を含めることはできますか?
回答: Java 8では、静的修飾子と最終修飾子を使用して定数変数を使用できます。ただし、Javaインターフェイスにインスタンス変数を含めることはできません。インターフェイスでインスタンス変数を宣言しようとすると、コンパイラエラーが発生します。
Q#3)Java 8のインターフェースの改善点は何ですか?
回答: Java 8のインターフェースの最も重要な改善点は、静的メソッドとデフォルトメソッドがインターフェースで許可されることです。メソッドを静的またはデフォルトとして宣言し、インターフェース内で定義することができます。
Q#4)Javaインターフェースのデフォルトメソッドをオーバーライドできますか?
回答: いいえ。インターフェースのデフォルトのメソッドをオーバーライドする必要はありません。これは、クラスにインターフェイスを実装すると、そのクラスのデフォルトメソッドに実装クラスがアクセスできるためです。したがって、実装クラスのオブジェクトを使用して、インターフェイスのデフォルトメソッドにアクセスできます。
Q#5)インターフェイスはJavaでフィールドを持つことができますか?
ソフトウェア開発ライフサイクルの段階
回答: はい、Javaのインターフェースにフィールドまたは変数を含めることができますが、デフォルトでは、これらのフィールドはすべて静的、最終、およびパブリックです。
結論
このチュートリアルでは、Java 8でインターフェースに加えられた変更について説明しました。Java8では、インターフェースに静的メソッドとデフォルトメソッドが導入されました。以前は、インターフェースに抽象メソッドしか含めることができませんでした。ただし、Java 8以降では、Javaでデフォルトメソッドと静的メソッドを定義できます。
また、Java 8では、Javaの関数型インターフェースでラムダ式を使用できます。次に、抽象クラスとインターフェースについても説明し、Javaでそれぞれをいつ使用するかを確認しました。 Javaでの列挙型の継承も確認しました。
また、拡張と実装、クラスとインターフェイス、抽象クラスとインターフェイスなどの違いについても説明しました。
=> ここですべてのJavaチュートリアルを確認してください。