【问题标题】:What is the "default" implementation of method defined in an Interface?接口中定义的方法的“默认”实现是什么?
【发布时间】:2013-08-17 07:21:06
【问题描述】:

在集合接口中,我找到了一个名为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 关键字是什么,它是如何工作的?

【问题讨论】:

标签: java interface java-8


【解决方案1】:

来自https://dzone.com/articles/interface-default-methods-java

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();
    }
}

【讨论】:

  • 谢谢,很好的说明。在我有机会提问之前,你就回答了我所有的问题。
  • 为什么不使用 abstract 代替?
  • @AstolfoHoscher 只能扩展一个类,但可以实现多个接口。
【解决方案2】:

这些方法称为默认方法。 默认方法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

有用的链接:

【讨论】:

  • 那么如果一个类实现了一个接口而不实现它的方法就可以了吗?就我使用的 Java7 而言,这是不允许的。
  • @AniketThakur。这在 Java 8 之前是不允许的。此功能仅在 Java 8 中添加。您可以避免在实现类中提供 default 方法的实现。
  • @PawanMishra。见我之前的评论。不,您不需要在实现类中提供默认接口方法的实现。
  • @PawanMishra 你可以覆盖它。没有限制,例如您只需要使用默认实现。
  • 向前迈出的一步,最终将避免被多重继承所困扰!
【解决方案3】:

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

存在的问题

普通接口方法被声明为抽象的,并且必须在实现该接口的类中定义。这“负担”了负责实现每个声明的方法的类实现者。更重要的是,这也意味着在“发布”之后扩展接口是不可能的。否则,所有实现者都必须调整他们的实现,破坏向后的源代码和二进制兼容性。

Java 8 采用的解决方案

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

注意事项

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-07-31
    • 2014-12-06
    • 2012-09-25
    • 2011-03-17
    • 2016-06-16
    • 2014-10-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多