Java 8 の新機能: デフォルトのインターフェース・メソッド

黄舟
リリース: 2017-02-23 10:25:28
オリジナル
1493 人が閲覧しました

要約: Java8 以降、インターフェースはメソッドを宣言するだけの場所ではなく、メソッドを宣言するときにメソッドにデフォルトの実装を与えることもできます。これにより、メソッドを実装するすべてのサブクラスがそれをデフォルトのインターフェースメソッドと呼びます。インターフェースは、このメソッドのデフォルト実装を保持できます。

1. デフォルトインターフェースメソッド導入の背景

java8 は、Java のバージョン更新の反復プロセスの中で最も変更されたバージョンと見なすことができます (生き残るためには時代に遅れずについていくべきです)。しかしその後、何年にもわたる開発と反復を経て、Java のソース コードは巨大なものになりました。これほど膨大な量の作業を行うのは決して簡単ではありません。そのため、Java 8 のデフォルトのインターフェイス メソッドを初めて見たとき、最初に感じたのは、これは Java 設計者が埋める前に掘った穴ではないかということでした。

これまでの説明から、Java8 では List の

sort(Comparator<? super E> c)
ログイン後にコピー

メソッドなど、既存のインターフェースに多くのメソッドが追加されていることがわかりました。 Java 8 より前のインターフェースの設計思想に従っている場合、インターフェースにメソッド宣言を追加するとき、インターフェースを実装するクラスは、新しく追加されたメソッドに対応する実装を追加する必要があります。互換性を考慮すると、これはお勧めできません。したがって、これは落とし穴であり、新しい機能では、ケーキを食べたりするために、インターフェイスにいくつかの新しいメソッドを追加する必要があります。Java8 の設計者は、デフォルトのインターフェイス メソッドを提案しました。 。 の概念。

このように、デフォルトのインターフェースメソッドは、私たち一般の開発者にとってはまだまだ遠いところにあるAPI設計者向けに開発されているようですが、JDKを設計する必要はありませんが、それでもそう考える必要があります。日常の開発プロセスでは、他のビジネス パーティが呼び出すための API を提供する必要がありますが、API を更新するときに、互換性を維持しながら、デフォルトのメソッドを使用して、より高度な機能を提供できます。

2. デフォルトのインターフェースメソッドの定義

デフォルトのインターフェースメソッドの定義は非常に簡単で、次のようにインターフェースのメソッド定義の前に

default
ログイン後にコピー

キーワードを追加するだけです。このように、メソッドの後は、インターフェイスを実装するすべてのサブクラスが間接的にメソッドを保持します。あるいは、私と同じように、インターフェイスと抽象クラスはますます似てきていると感じるかもしれませんが、実際には、それらの間には次のような違いがあります:

1. クラスは 1 つのクラスのみを継承できますが、複数のインターフェイスを実装できます


2抽象クラスは変数を定義できますが、インターフェイスは定義できません。上で述べた問題を解決することに加えて、抽象化には次の利点もあります。これにより、サブクラスで無意味に実装することがなくなります (通常は new UnsupportedException() をスローします)

2. デフォルトのメソッドは、Java での多重継承の新しい方法を提供します (継承できるクラスは 1 つだけですが、複数のインターフェイスを実装できます)。 、インターフェイスでデフォルト メソッドを定義できるようになりました)


3. 競合とその解決策

クラスは複数のインターフェイスを実装できるため、クラスが複数のインターフェイスを実装する場合、これらのインターフェイスでデフォルト メソッドが 2 つ以上ある場合に競合が発生します。 Java8 では、競合を解決するために次の 3 つの原則を定義しています:

1. クラスまたは親クラスで明示的に宣言されたメソッドは、デフォルトのメソッドよりも優先されます

2. ルール 1 が失敗した場合は、デフォルトを選択します。現在のクラスに最も近い特定の実装を持つメソッド

3. ルール 2 も失敗する場合は、インターフェースを明示的に指定する必要があります
以下は、いくつかの例を通して説明します:

例 1


public interface A {
    /**
     * 默认方法定义
     */
    default void method() {
        System.out.println("This is a default method!");
    }
}
ログイン後にコピー

ここでは、インターフェースB は A よりも C に近く、ルール 2 に従って B のメソッドは特定のデフォルト実装であるため、ここで実際に呼び出されるのはインターフェイス B のデフォルトです。メソッド

例 2

public interface A {
    /**
     * 默认方法定义
     */
    default void method() {
        System.out.println("A&#39;s default method!");
    }
}
public interface B extends A {
    /**
     * 默认方法定义
     */
    default void method() {
        System.out.println("B&#39;s default method!");
    }
}
public class C implements A, B {
    public static void main(String[] args) {
        new C().method();
    }
}
// 输出:B&#39;s default method!
ログイン後にコピー

例 2 では、クラス D を追加します。元のインターフェイス A と B に基づいてインターフェイス A を実装します。次に、クラス C が D から継承し、A と B を実装します。C は D からより近く分離されていますが、D の特定の実装は A にあるため、B のデフォルト メソッドはそのままです。最も近いデフォルトの実装。ルール 2 に従って、B のデフォルト メソッドがここで実際に呼び出されます。


例 3

public class D implements A {
}
public class C extends D implements A, B {
    public static void main(String[] args) {
        new C().method();
    }
}
// 输出:B&#39;s default method!
ログイン後にコピー

例 3 では、インターフェイス B はインターフェイス A から継承しなくなり、この時点でデフォルト メソッド


// A接口不变
public interface B {
    /**
     * 默认方法定义
     */
    default void method() {
        System.out.println("B&#39;s default method!");
    }
}
public class C implements A, B {
    @Override
    public void method() {
        // 必须显式指定
        B.super.method();
    }
    public static void main(String[] args) {
        new C().method();
    }
}
ログイン後にコピー

が C で呼び出されます。インターフェイス A とインターフェイスの特定の実装から同じ距離にあります。 B. コンパイラはそれを判断できないため、エラーが報告されます。今回は明示的に指定する必要があります:
method()
ログイン後にコピー


上記は、Java8 の新機能、デフォルトのインターフェイス メソッドの内容です。さらに関連する内容については、PHP 中国語 Web サイト (www.php.cn) に注目してください。

-->


関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート