接口中定义的方法的“默认”实现是什么?
在Collection接口中,我find了一个名为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 8引入了“默认方法”或(Defender方法)新特性,允许开发人员在不破坏这些接口的现有实现的情况下向接口添加新的方法。 它提供了灵活性来允许接口定义的实现,在具体类无法为该方法提供实现的情况下,它将默认使用。
public interface A { default void foo(){ System.out.println("Calling A.foo()"); } } public class ClassAB implements A { }
有一个常见的问题是,当人们第一次听到这个新function时,他们会询问有关默认方法:
如果类实现了两个接口,并且这两个接口定义了一个具有相同签名的默认方法呢?
举例来说明这种情况:
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(); } }
这些方法被称为默认方法。 默认方法或Defender方法是Java 8中新增加的function之一。
它们将被用来允许一个接口方法提供一个默认的实现,当一个具体的类不提供该方法的实现时。
所以,如果你有一个接口,用一个默认的方法:
public interface Hello { default void sayHello() { System.out.println("Hello"); } }
以下课程完全有效:
public class HelloImpl implements Hello { }
如果你创build一个HelloImpl
的实例:
Hello hello = new HelloImpl(); hello.sayHello(); // This will invoke the default method in interface
有用的链接:
- 更新的Oracle教程
- 关于Java 8的一切
- 后卫方法
我做了一些研究,发现了以下内容。 希望这可以帮助。
存在的问题
普通的接口方法被声明为抽象的,并且必须在实现接口的类中定义。 这“负担”class级执行者,负责执行每一个已经公布的方法。 更重要的是,这也意味着在“发布”之后扩展接口是不可能的。 否则,所有的实现者将不得不调整他们的实现,打破源代码和二进制兼容性。
Java 8中采用的解决scheme
为了解决这些问题,JDK 8的新特性之一就是可以使用缺省方法扩展现有的接口。 默认方法不仅被声明,而且在接口中定义。
需要注意的重点
- 实施者可以select不实施默认方法来实施课程。
- 实现者仍然可以重写默认方法,就像常规的非最终类方法可以在子类中重写。
- 抽象类甚至可以(重新)将缺省方法声明为抽象,强制子类重新实现该方法(有时称为“重新抽象”)。