インターフェースの静的メソッドとデフォルトメソッドの違い


107

インターフェイスで静的メソッドとデフォルトメソッドを定義できるようになったことに気付いたとき、私はインターフェイスを学習していました。

public interface interfacesample2 {
    public static void method() {
        System.out.println("hello world");
    }

    public default void menthod3() {
        System.out.println("default print");
    }
}

2つの違いを説明してください。また、いつ使用するかについての例がある場合は、これがいいでしょう。インターフェイスで少し混乱しています。


4
Javaチュートリアルで静的メソッドを読んでみましたか?
Dawood ibnカリーム2015年

1
静的メソッドをオーバーライドできないという部分を見逃しましたか?
Dawood ibnカリーム2015年

1
インターフェイスでは同じことが理解できません
Vipin Menon

9
静的メソッドはインターフェースの静的メンバーであり、(クラスと同様に)default implementationオーバーライドできません。デフォルトのメソッドは、オーバーライドされる可能性のあるメソッドのメソッドです。
Shail016 2015年

2
ただ疑問に思う:なぜあなたはここで答えを決して受け入れなかったのですか?
GhostCat 2016年

回答:


116

Java 8の静的メソッドとデフォルトメソッドの違い:

1)デフォルトのメソッド実装クラスでオーバーライドできますが、静的メソッドオーバーライドできません

2)静的メソッドはインターフェイスクラスにのみ属しているため、このインターフェイスを実装するクラスではなく、インターフェイスクラスでのみ静的メソッドを呼び出すことができます。以下を参照してください。

public interface MyInterface {
    default void defaultMethod(){
        System.out.println("Default");
    }

    static void staticMethod(){
        System.out.println("Static");
    }    
}

public class MyClass implements MyInterface {

    public static void main(String[] args) {

        MyClass.staticMethod(); //not valid - static method may be invoked on containing interface class only
        MyInterface.staticMethod(); //valid
    }
}

3)クラスとインターフェースの両方に同じ名前の静的メソッドを含めることができ、どちらも他をオーバーライドしません!

public class MyClass implements MyInterface {

    public static void main(String[] args) {

        //both are valid and have different behaviour
        MyClass.staticMethod();
        MyInterface.staticMethod();
    }

    static void staticMethod(){
        System.out.println("another static..");
    }
}

2
しかし、なぜ「静的」ですか?Java 8ではどのような目的に役立ちますか?
Shashank Vivek 2018年

4
staticキーワードの目的は変更されていません。クラスレベルのメンバー(フィールド、メソッドなど)を定義するためです。Java8では、この動作がインターフェイスに拡張されたため、クラスに類似し、ほとんどのシナリオでクラスを置き換えることができます。
スティンガー2018年

そうですが、オーバーライドする代わりに、インターフェイスの静的メソッドを非表示にすることができます.....私は両方 が同じことを満たしpurpose共通の実装を使用)、あいまいさをimplementing the logic again in subclass オーバーライド、非表示)によって解決する と思うだけです。唯一の賢明な理由は、[静的インターフェイスメソッドが継承されない](stackoverflow.com/questions/25169175/…)という理由によるものであり、サブクラスインスタンスを使用してそれらを呼び出すことはできません。
amarnathは、

29

静的メソッドは、いわば「名前空間」クラスに適用されるメソッドです。したがって、インターフェースのstaticメソッドfooInterfaceによってアクセスされInterface.foo()ます。関数呼び出しは、インターフェイスの特定のインスタンスには適用されないことに注意してください。

bar一方、デフォルトの実装は、

Interface x = new ConcreteClass();
x.bar();

staticインターフェイスメソッドが知っていることができないthis変数が、デフォルトの実装ができます。


19

1. 2つの違いを説明する

静的インターフェイスメソッドは、静的クラスメソッドに似ています(ここでは、インターフェイスのみに属しています)。デフォルトのインターフェースメソッドが提供するdefault implementationインターフェースメソッド(実装クラスが提供する可能性があるoverride)が
、クラスがimplementing more than one interface with same defaultメソッドシグネチャである場合は、実装クラスneeds to override the default method

以下の簡単な例を見つけることができます(さまざまなケースでDIYできます)

public class Test {
    public static void main(String[] args) {
        // Accessing the static member
        I1.hello();

        // Anonymous class Not overriding the default method
        I1 t = new I1() {
            @Override
            public void test() {
                System.out.println("Anonymous test");
            }
        };
        t.test();
        t.hello("uvw");

        // Referring to class instance with overridden default method
        I1 t1 = new Test2();
        t1.test();
        t1.hello("xyz");

    }
}

interface I1 {

    void test();
    //static method
    static void hello() {
        System.out.println("hello from Interface I1");
    }

    // default need not to be implemented by implementing class
    default void hello(String name) {
        System.out.println("Hello " + name);
    }
}

class Test2 implements I1 {
    @Override
    public void test() {
        System.out.println("testing 1234...");
    }

    @Override
    public void hello(String name) {
        System.out.println("bonjour" + name);
    }
}

2.いつ使用するのがよいでしょう。

問題の内容によって異なります。そのコントラクトのすべてのクラスで仕様のメソッドに同じ実装が必要な場合は、デフォルトメソッドが便利ですAdapter。または、クラスのように使用できます。

これは良い読み物です:https : //softwareengineering.stackexchange.com/questions/233053/why-were-default-and-static-methods-added-to-interfaces-in-java-8-when-we-alread

また、以下のOracleドキュメントでは、既存のインターフェースを進化させるためのデフォルトおよび静的メソッドについて説明しています。

新しいデフォルトまたは静的メソッドで拡張されたインターフェースを実装するクラスを持つユーザーは、追加のメソッドに対応するためにそれらを変更または再コンパイルする必要はありません。

http://docs.oracle.com/javase/tutorial/java/IandI/nogrow.html


私は疑問を持っています。インターフェイスのオブジェクトを作成することは可能ですか?あなたのコードには次の行があります:I1 t = new I1()
Hackinet

@Hackinetは、その声明についてのJavaコメントを親切に読んでください。匿名クラスについてもお読みください。お役に立てば幸いです。
Shail016 2018年

12

これが私の見解です:

インターフェースの静的メソッド

  • 直接呼び出すことができます(InterfacetA.staticMethod())

  • サブクラスはオーバーライドできません。

  • サブクラスはstaticMethodと同じ名前のメソッドを持つことができます

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

  • 直接呼び出すことはできません。

  • サブクラスはそれをオーバーライドできます

利点:

  • staticメソッド:ユーティリティメソッド用に個別のクラスを作成する必要はありません。

  • defaultメソッド:defaultメソッドに共通の機能を提供します。


8

このリンクにはいくつかの有用な洞察があり、それらのいくつかをここにリストしました。

デフォルトおよび静的メソッドは、インターフェース抽象クラスの違いを埋めました。

インターフェイスのデフォルトメソッド:

  • これは、すべてのコレクションクラスのメソッドをインターフェイス自体で提供できるなど、ユーティリティクラスを回避するのに役立ちます。
  • 実装クラスを壊すことを恐れずにインターフェースを拡張するのに役立ちます。

静的メソッドのインターフェース:

  • これらはインターフェースの一部であり、実装クラスオブジェクトには使用できません。
  • 実装クラスがそれらをオーバーライドできないようにすることで、セキュリティを提供するのに役立ちます。

別の有用なリファレンスを引用したい。


3

インターフェイスのデフォルトメソッド:

これは、すべてのコレクションクラスのメソッドをインターフェイス自体で提供できるなど、ユーティリティクラスを回避するのに役立ちます。

実装クラスを壊すことを恐れずにインターフェースを拡張するのに役立ちます。

静的メソッドのインターフェース:

これらはインターフェースの一部であり、実装クラスオブジェクトには使用できません。

実装クラスがそれらをオーバーライドできないようにすることで、セキュリティを提供するのに役立ちます。

静的メソッドがセキュリティを提供する方法。例を見てみましょう。

interface MyInterface {
    /*
     * This is a default method so we need not to implement this method in the implementation classes
     */
    default void newMethod() {
        System.out.println("Newly added default method in Interface");
    }

    /*
     * This is a static method. Static method in interface is similar to default method except that we cannot override them in the implementation classes. Similar to default methods, we need to implement these methods in implementation classes so we can safely add them to the existing interfaces.
     */
    static void anotherNewMethod() {
        System.out.println("Newly added static method in Interface");
    }

    /*
     * Already existing public and abstract method We must need to implement this method in implementation classes.
     */
    void existingMethod(String str);
}

public class Example implements MyInterface {
    // implementing abstract method
    public void existingMethod(String str) {
        System.out.println("String is: " + str);
    }

    public void newMethod() {
        System.out.println("Newly added default method in Class");
    }

    static void anotherNewMethod() {
        System.out.println("Newly added static method in Class");
    }

    public static void main(String[] args) {
        Example obj = new Example();

        // calling the default method of class
        obj.newMethod();
        // calling the static method of class

        obj.anotherNewMethod();

        // calling the static method of interface
        MyInterface.anotherNewMethod();

        // calling the abstract method of interface
        obj.existingMethod("Java 8 is easy to learn");

    }
}

ここでobj.newMethod();クラス実装ロジックを出力するということは、実装クラス内でそのメソッドのロジックを変更できることを意味します。

しかしobj.anotherNewMethod();、クラス実装ロジックを出力しますが、インターフェース実装は変更しません。したがって、そのメソッド内に暗号化/復号化ロジックが記述されている場合、変更することはできません。


この答えはどこかうまくいっているようで、突然ブームになりました!最後に意味のある説明はありません。インターフェイスの実装は変更されていませんが、これはどういう意味ですか?
amarnathは、

2

OracleのJavadocsによると:http : //docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html

デフォルトのメソッドを使用すると、ライブラリのインターフェースに新しい機能を追加し、それらのインターフェースの古いバージョン用に作成されたコードとのバイナリ互換性を確保できます。

静的メソッドは、オブジェクトではなく、それが定義されているクラスに関連付けられているメソッドです。クラスのすべてのインスタンスは、その静的メソッドを共有します。

通常、インターフェースの静的メソッドはヘルパーメソッドとして使用され、デフォルトメソッドはそのインターフェースを実装するクラスのデフォルト実装として使用されます。

例:

interface IDemo {

    //this method can be called directly from anywhere this interface is visible
    static int convertStrToInt(String numStr) {
       return Integer.parseInt(numStr);
    }


    //getNum will be implemented in a class
    int getNum();       

    default String numAsStr() {
       //this.getNum will call the class's implementation
       return Integer.toString(this.getNum());
    }   

}

1

あたりとしてJava14 JLSドキュメント:

デフォルトの方法:

  • デフォルトの修飾子を持つインターフェースで宣言されたインスタンスメソッドです。

  • 実装クラスのインスタンスのみがアクセスできます

  • その本体は常にブロックで表され、メソッドをオーバーライドせずに、実装クラスのデフォルトの実装または動作を提供します

  • 静的またはプライベートにすることはできません

静的メソッド:

  • クラスの静的メソッドと同様に、特定のオブジェクトを参照せずにインターフェイスから呼び出すことができます。

  • 静的メソッドはプライベートにすることができます

  • 実装クラスは静的メソッドにアクセスできません

以下のサンプルコードの助けを借りてそれを理解しましょう:

            public interface MyInterface {
        
            private void privateMethod() {
                System.out.println("Hi, this is privateMethod");
            }
        
            private static void staticPrivateMethod() {
                System.out.println("Hi, this is staticPrivateMethod");
            }
        
            static void staticMethod() {
                //privateMethod();    // Non-static method cannot be referenced from a static contex
                System.out.println("Hi, this is staticMethod");
                staticPrivateMethod();
            }
        
            default void defaultMethod() {
                System.out.println("Hi, this is defaultMethod");
            }
        
        }
    
    public class MyInterfaceImpl implements MyInterface{
        public static void main(String[] args) {
    
            MyInterface.staticMethod();
            // myInterface.staticMethod(); // Not allowed
    
            MyInterface myInterface = new MyInterfaceImpl();
            myInterface.defaultMethod();
            // MyInterface.defaultMethod(); // Not allowed
    
        }
    }

0

Interfacesample2.menthod3();静的メソッドではないため実行できません。実行するにmethod3()は、Interfacesample2インターフェースのインスタンスが必要です。

次の実用的な例を見つけてください:

public class Java8Tester {
   public static void main(String args[]){
      // Interfacesample2.menthod3(); Cannot make a static reference to the non-static method menthod3 from the type Interfacesample2

      new Interfacesample2(){ }.menthod3();// so in order to call default method we need an instance of interface

       Interfacesample2.method(); // it
   }
}

interface Interfacesample2 {
    public static void method() {
        System.out.println("hello world");
    }

    public default void menthod3() {
        System.out.println("default print");
    }
}

0

Java 8インターフェースの開始には、静的メソッドを含めることもできます。クラスの静的メソッドと同様に、インターフェースの静的メソッドは、インターフェース名を使用して呼び出すことができます。

public interface Calculator {
    int add(int a, int b);
    int subtract(int a, int b);

    default int multiply(int a, int b) {
         throw new RuntimeException("Operation not supported. Upgrade to UltimateCalculator");
    }

    static void display(String value) {
        System.out.println(value);
    }
}

インターフェイスの静的メソッドとデフォルトメソッドの違いは、デフォルトメソッドは継承をサポートしていますが、静的メソッドはサポートしていません。デフォルトのメソッドは、継承するインターフェースでオーバーライドできます。

インターフェースのデフォルトメソッドと静的メソッドについては、こちらをご覧ください。Java 8のインターフェースのデフォルトメソッド


0

ここですべての良い答え。静的関数の別の実用的な使い方をインターフェースに追加したいと思います。ヒントは、第2章「オブジェクトの作成と破棄」のJoshua Bloch著の本「Effective Java、3rd Edition」からきています。

Static functions can be used for static factory methods. 

静的ファクトリメソッドは、オブジェクトを返すメソッドです。それらはコンストラクタのように機能します。特定のケースでは、静的ファクトリメソッドは、コンストラクタを使用するよりも読みやすいコードを提供します。

本からの引用-Joshua BlochによるEffective Java、3rd Edition

Java 8より前は、インターフェースに静的メソッドを含めることができませんでした。慣例により、Typeという名前のインターフェイスの静的ファクトリメソッドは、Typesという名前のインスタンス化できないコンパニオンクラス(アイテム4)に入れられました。

著者は、そのような静的なファクトリメソッドが実装されているコレクションの例を示します。コードを確認すると、Josh BlochはCollectionsクラスの最初の作成者と見なすことができます。コレクションはクラスであり、インターフェースではありません。しかし、コンセプトはまだ適用されます。

たとえば、Java Collections Frameworkには、そのインタフェースの45のユーティリティ実装があり、変更不可能なコレクション、同期されたコレクションなどを提供しています。これらの実装のほぼすべては、インスタンス化できない1つのクラス(java.util.Collections)の静的ファクトリメソッドを介してエクスポートされます。返されるオブジェクトのクラスはすべて非公開です。

さらに、APIが小さいだけでなく、コードの読みやすさとAPIの使いやすさにも役立つと彼は説明しています。

削減されるのはAPIの大部分だけではなく、概念上の重要性、つまりAPIを使用するためにプログラマーが習得しなければならない概念の数と難しさです。プログラマーは、返されたオブジェクトがそのインターフェイスで指定されたAPIを正確に持っていることを知っているので、実装クラスの追加のクラスドキュメントを読む必要はありません。

以下は、java.util.Collectionsクラスの静的メソッドの1つです。

public static <T> Collection<T> unmodifiableCollection(Collection<? extends T> c) {
    return new UnmodifiableCollection<>(c);
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.