接口中定义的方法的“默认”实现是什么?

时间:2013-08-17 07:21:06

标签: java interface java-8

在Collection Interface中,我找到了一个名为removeIf()的方法,其中包含了它的实现。

default boolean removeIf(Predicate<? super E> filter) {
    Objects.requireNonNull(filter);  
    boolean removed = false;  
    final Iterator<E> each = iterator();   
    while (each.hasNext()) {  
        if (filter.test(each.next())) {  
            each.remove();  
            removed = true;  
        }  
    }  
    return removed;  
}  

我想知道是否有办法在界面中定义方法体? 什么是default关键字以及它是如何工作的?

3 个答案:

答案 0 :(得分:159)

Java 8引入了“默认方法”或(Defender方法)新功能,它允许开发人员在不破坏这些接口的现有实现的情况下向接口添加新方法。它提供了允许接口定义实现的灵活性,在具体类无法为该方法提供实现的情况下,该实现将默认使用。

public interface A {
    default void foo(){
       System.out.println("Calling A.foo()");
    }
}

public class ClassAB implements A {
}

当人们第一次听到新功能时,有一个常见的问题是人们会询问默认方法:

  

如果类实现了两个接口,并且这两个接口都定义了具有相同签名的默认方法,该怎么办?

举例说明这种情况:

public interface A {  
    default void foo(){  
        System.out.println("Calling A.foo()");  
    }  
}

public interface B {
    default void foo(){
        System.out.println("Calling B.foo()");
    }
}


public class ClassAB implements A, B {

}  

此代码无法使用以下结果进行编译:

java: class Clazz inherits unrelated defaults for foo() from types A and B

要解决这个问题,在Clazz中,我们必须通过覆盖冲突的方法来手动解决它:

public class Clazz implements A, B {
    public void foo(){}
}

但是如果我们想从接口A调用方法foo()的默认实现而不是实现我们自己的实现。

可以按如下方式引用A#foo():

public class Clazz implements A, B {
    public void foo(){
       A.super.foo();
    }
}

答案 1 :(得分:49)

这些方法称为默认方法。 默认方法 Defender方法是Java 8中的newly added features之一。

它们将用于允许接口方法在具体类不为该方法提供实现的情况下提供用作缺省的实现。

所以,如果你有一个接口,使用默认方法:

public interface Hello {
    default void sayHello() {
        System.out.println("Hello");
    }
}

以下课程完全有效:

public class HelloImpl implements Hello {

}

如果您创建HelloImpl的实例:

Hello hello = new HelloImpl();
hello.sayHello();  // This will invoke the default method in interface

有用的链接:

答案 2 :(得分:17)

我做了一些研究,我发现了以下内容。希望这会有所帮助。

  

存在的问题

普通接口方法声明为抽象,必须在实现接口的类中定义。这会给班级实施者带来“负担”,他们有责任实施所有宣称的方法。更重要的是,这也意味着在“发布”之后无法扩展接口。否则,所有实施者都必须调整其实现,打破后向源和二进制兼容性。

  

Java 8中采用的解决方案

为了解决这些问题,JDK 8的一个新功能是可以使用默认方法扩展现有接口。 默认方法不仅被声明,而且还在界面中定义。

  

需要注意的重要事项

  1. 实施者可以选择不实施默认方法 实施课程。
  2. 实施者仍然可以覆盖默认值 方法,如常规的非final类方法,可以重写 子类。
  3. 抽象类甚至可以(重新)声明默认方法 作为抽象,强制子类重新实现该方法(有时 称为“重新抽象”)。