关于java:界面中静态和默认方法的区别

Difference Between static and default methods in interface

当我通过接口学习时,我注意到您现在可以在接口中定义静态和默认方法。

1
2
3
4
5
6
7
8
9
public interface interfacesample2 {
    public static void method() {
        System.out.println("hello world");
    }

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

请解释一下这两者的区别,如果有一个我们什么时候使用的例子,那就更好了。界面有点混乱。


Java 8中静态方法与默认方法的区别:

1)默认方法可以在实现类中被重写,而静态方法不能。

2)静态方法只属于接口类,因此只能在接口类上调用静态方法,而不能在实现此接口的类上调用静态方法,请参见:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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)类和接口都可以有同名的静态方法,并且不能重写其他方法!

1
2
3
4
5
6
7
8
9
10
11
12
13
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..");
    }
}


可以说,静态方法是应用于类"命名空间"的方法。因此,Interface.foo()访问接口Interfacefoo方法。请注意,函数调用不适用于接口的任何特定实例。

另一方面,默认实现bar由调用

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

static接口方法不能知道this变量,但默认实现可以。


1. explain the difference of the two

静态接口方法类似于静态类方法(这里它们只属于接口)。其中,作为默认接口方法,提供接口方法的default implementation(实现类可以是override
但是记住,如果一个类是implementing more than one interface with same default方法签名,那么实现类needs to override the default method就可以了。

您可以在下面找到一个简单的例子(可以针对不同的情况进行DIY)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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. when we would use this would be nice.

这取决于你的问题陈述。如果您的规范中的某个方法在该契约中的所有类中都需要相同的实现,或者它可以像Adapter类那样使用,那么缺省方法是有用的。

这里有一个很好的读物:https://softwarengineering.stackexchange.com/questions/233053/why-were-default-and-static-methods-added-to-interfaces-in-java-8-when-we-alread

下面的Oracle文档还解释了用于改进现有接口的默认和静态方法:

Users who have classes that implement interfaces enhanced with new
default or static methods do not have to modify or recompile them to
accommodate the additional methods.

http://docs.oracle.com/javase/tutorial/java/iandi/nogrow.html网站


这个链接有一些有用的见解,这里列出了其中的一些。

默认和静态方法消除了接口和抽象类之间的差异。

接口默认方法:

  • 它有助于避免实用程序类,例如所有集合类方法都可以在接口本身中提供。
  • 它有助于扩展接口,而不必担心破坏实现类。

接口静态方法:

  • 它们是接口的一部分,我们不能将其用于实现类对象。
  • 它通过不允许实现类重写它们来帮助提供安全性。

喜欢引用另一个有用的参考。


这是我的观点:

接口中的静态方法:

  • 您可以直接调用它(interfaceta.staticMethod())

  • 子类将无法重写。

  • 子类可以具有与StaticMethod同名的方法

接口中的默认方法:

  • 你不能直接打电话给它。

  • 子类将能够覆盖它

优势:

  • 静态方法:不需要为实用方法创建单独的类。

  • 默认方法:在默认方法中提供通用功能。


接口默认方法:

它有助于避免实用程序类,例如所有集合类方法都可以在接口本身中提供。

它有助于扩展接口,而不必担心破坏实现类。

接口静态方法:

它们是接口的一部分,我们不能将其用于实现类对象。

它通过不允许实现类重写它们来帮助提供安全性。

现在,静态方法如何提供安全性。让我们看一个例子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
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();打印类实现逻辑,但不改变接口实现。因此,如果在该方法中写入任何加密解密逻辑,您就不能更改。


根据Oracle的java docs:http://docs.oracle.com/javase/tutorial/java/iandi/defaultmethods.html

Default methods enable you to add new functionality to the interfaces of your libraries and ensure binary compatibility with code written for older versions of those interfaces.

A static method is a method that is associated with the class in which it is defined rather than with any object. Every instance of the class shares its static methods.

通常,接口中的静态方法用作辅助方法,而默认方法用作实现该接口的类的默认实现。

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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());
    }  

}

我们不能执行Interfacesample2.menthod3();,因为它不是静态方法。为了执行method3(),我们需要一个Interfacesample2接口的实例。

请找到以下实用示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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");
    }
}