ホームページ  >  記事  >  类库下载  >  Java8 の新機能 - デフォルトのインターフェースメソッド

Java8 の新機能 - デフォルトのインターフェースメソッド

高洛峰
高洛峰オリジナル
2016-10-15 10:37:131592ブラウズ

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

Java8は、度重なるJavaのバージョンアップの過程で最も変化したバージョンと言える(生き残るためには時代に遅れずについていくべきだろう)が、その後は長年の開発と反復により、Java のソース コードはすでに巨大になっており、このような膨大な量の作業を行うのは決して簡単ではありません。そのため、Java 8 のデフォルトのインターフェイス メソッドを初めて見たとき、最初に感じたのは、これは Java 設計者が埋める前に掘った穴ではないかということでした。
これまでの説明から、Java8 では List の sort(Comparator super E> c) メソッドなど、既存のインターフェースに多くのメソッドが追加されたことがわかりました。 Java 8 より前のインターフェースの設計思想に従っている場合、インターフェースにメソッド宣言を追加するとき、インターフェースを実装するクラスは、新しく追加されたメソッドに対応する実装を追加する必要があります。互換性を考慮すると、これはお勧めできません。したがって、これは落とし穴であり、新しい機能では、両方の長所を活かすために、インターフェイスにいくつかの新しいメソッドを追加する必要があります。Java8 の設計者は、デフォルトのインターフェイス メソッドという概念を提案しました。
このように、デフォルトのインターフェースメソッドは、私たち一般の開発者からはまだ遠いところにある API 設計者向けに開発されているようです。JDK を設計する必要はありませんが、このように考えるのは少し簡単です。日々の開発プロセス 他のビジネス パーティが呼び出すための API を提供する必要は依然としてありますが、API を更新する場合、互換性を維持しながら、デフォルトのメソッドを使用して、より高度な機能を提供できます。

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

デフォルトのインターフェースメソッドの定義は非常に簡単で、次のようにインターフェースのメソッド定義の前にdefaultキーワードを追加するだけです。

public interface A {    /**
     * 默认方法定义
     */
    default void method() {
        System.out.println("This is a default method!");
    }

}

このようにデフォルトのメソッドを定義すると、すべてこのインターフェースのサブクラスはすべて、このメソッドを間接的に保持します。あるいは、私と同じように、インターフェイスと抽象クラスはますます似てきていると感じるかもしれませんが、確かに、それらの間には次のような違いがあります:

1. 一个类只能继承一个类,但是可以实现多个接口

2. 抽象类可以定义变量,而接口却不能

上で述べた問題を解決することに加えて、抽象化には次の利点もあります。

1. すべてのサブクラスで必要ない一部のメソッドについては、サブクラスでの無意味な実装を避けるためにデフォルトの実装を与えます (通常は new UnsupportedException() をスローします) 2. デフォルトのメソッドは Java です 多重継承により新しい方法が提供されます(継承できるクラスは 1 つだけですが、複数のインターフェイスを実装でき、インターフェイスでデフォルトのメソッドも定義できるようになりました)

3. 競合とその解決策

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

1 クラスまたは親クラスで明示的に宣言されたメソッドの優先順位が高くなります。すべてのデフォルトのメソッド 2. ルール 1 が失敗した場合、現在のクラスに最も近い特定の実装を持つデフォルトのメソッドが選択されます 3. ルール 2 も失敗した場合は、インターフェイスを明示的に指定する必要があります

以下は、いくつかの例を通して説明されます。 :

例 1

public interface A {    /**
     * 默认方法定义
     */
    default void method() {
        System.out.println("A's default method!");
    }
}public interface B extends A {    /**
     * 默认方法定义
     */
    default void method() {
        System.out.println("B's default method!");
    }
}public class C implements A, B {    public static void main(String[] args) {        new C().method();
    }
}// 输出:B's default method!

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

例 2

public class D implements A {
}public class C extends D implements A, B {    public static void main(String[] args) {        new C().method();
    }
}// 输出:B's default method!

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

例 3

// A接口不变public interface B {    /**
     * 默认方法定义
     */
    default void method() {
        System.out.println("B'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();
    }
}

例 3 では、インターフェイス B はインターフェイス A を継承しなくなりました。そのため、この時点で、C で呼び出されるデフォルトのメソッド method() は、インターフェイス A と B の特定の実装距離から同じ距離になります。コンパイラは判断できないため、明示的に指定する必要があります: B.super.method()。


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。