显式调用Java中的默认方法


247

Java 8引入了默认方法,以提供扩展接口的功能,而无需修改现有的实现。

我想知道当由于不同接口中的默认实现冲突而导致该方法的默认实现被重写或不可用时,是否可以显式调用该方法的默认实现。

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

class B implements A {
    @Override
    public void foo() {
        System.out.println("B.foo");
    }
    public void afoo() {
        // how to invoke A.foo() here?
    }
}

考虑上面的代码,您将如何A.foo()从B类的方法调用?


您能告诉我为什么在接口A ??中对foo()方法实现了吗?
Maciej Cygan

20
@MaciejCygan Java 8中允许使用
Rohit Jain

Answers:


329

按照这篇文章,你在界面访问默认方法A使用

A.super.foo();

这可用于如下(假设接口AC两个有默认的方法foo()

public class ChildClass implements A, C {
    @Override    
    public void foo() {
       //you could completely override the default implementations
       doSomethingElse();
       //or manage conflicts between the same method foo() in both A and C
       A.super.foo();
    }
    public void bah() {
       A.super.foo(); //original foo() from A accessed
       C.super.foo(); //original foo() from C accessed
    }
}

A并且C可以同时具有.foo()方法,可以选择特定的默认实现,也可以将一个(或两个)用作新foo()方法的一部分。您也可以使用相同的语法在实现类中的其他方法中访问默认版本。

方法调用语法的形式描述可以在JLS第15章中找到。


14
另请注意,如果A extends SomeOtherInterfaceSomeOtherInterface都具有default Type method(),则您不能只SomeOtherInterface.super.method()从ChildClass进行调用。您只能调用ChildClass“ s” implements子句中列举的接口的默认方法,而不能调用其父接口的方法。
gvlasov 2015年

1
@Suseika好点,就像没有一样super.super.someMethod();(因为那太可怕了)
理查德·

@gvlasov很好,但是如何从子接口访问父接口的默认方法,这可能吗?更新.............是的,这里有更具体的解释stackoverflow.com/a/24280376/3791156
Raaghu

@RichardTingle完美无缺的答案!
gaurav

17

下面的代码应该工作。

public class B implements A {
    @Override
    public void foo() {
        System.out.println("B.foo");
    }

    void aFoo() {
        A.super.foo();
    }

    public static void main(String[] args) {
        B b = new B();
        b.foo();
        b.aFoo();
    }
}

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

输出:

B.foo
A.foo

我认为这是描述上述问题的最佳示例。谢谢
Hemanth Peela '19

8

此答案主要是为来自问题45047550(已关闭)的用户编写的。

Java 8接口介绍了多重继承的某些方面。默认方法具有一个已实现的功能主体。要从超类调用方法,可以使用关键字super,但是如果要使用超接口来实现它,则需要显式命名它。

class ParentClass {
    public void hello() {
        System.out.println("Hello ParentClass!");
    }
}

interface InterfaceFoo {
    default public void hello() {
        System.out.println("Hello InterfaceFoo!");
    }
}

interface InterfaceBar {
    default public void hello() {
        System.out.println("Hello InterfaceBar!");
    }
}

public class Example extends ParentClass implements InterfaceFoo, InterfaceBar {
    public void hello() {
        super.hello(); // (note: ParentClass.super is wrong!)
        InterfaceFoo.super.hello();
        InterfaceBar.super.hello();
    }

    public static void main(String[] args) {
        new Example().hello();
    }
}

输出:

家长班您好!
您好InterfaceFoo!
您好InterfaceBar!


3

您无需覆盖接口的默认方法。像下面这样调用它:

public class B implements A {

    @Override
    public void foo() {
        System.out.println("B.foo");
    }

    public void afoo() {
        A.super.foo();
    }

    public static void main(String[] args) {
       B b=new B();
       b.afoo();
    }
}

输出:


9
OP说:“当方法被重写时,[是否]可以显式调用该方法的默认实现”
dasblinkenlight 2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.