【问题标题】:Explicitly calling a default method in Java在 Java 中显式调用默认方法
【发布时间】:2021-10-07 01:37:04
【问题描述】:

Java 8 引入了default methods 以提供扩展接口的能力,而无需修改现有实现。

我想知道当某个方法已被覆盖或由于不同接口中的默认实现冲突而无法使用时,是否可以显式调用该方法的默认实现。

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?
    }
}

考虑到上面的代码,你会如何从 B 类的方法中调用 A.foo()

【问题讨论】:

  • 你能告诉我为什么你的 foo() 方法在你的接口 A 中有实现吗??。
  • @MaciejCygan 在 Java 8 中是允许的

标签: java inheritance interface java-8 default-method


【解决方案1】:

根据this article,您可以使用接口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
    }
}

AC 都可以具有 .foo() 方法,并且可以选择特定的默认实现,或者您可以使用一个(或两者)作为新的 foo() 方法的一部分。您还可以使用相同的语法来访问实现类中其他方法的默认版本。

方法调用语法的正式描述可以在chapter 15 of the JLS中找到。

【讨论】:

  • 另请注意,如果A extends SomeOtherInterfaceSomeOtherInterfacedefault Type method(),那么您不能只从ChildClass 调用SomeOtherInterface.super.method()。您只能调用在ChildClassimplements 子句中枚举的接口的默认方法,而不是其父接口的方法。
  • @Suseika 好点,就像没有super.super.someMethod(); 一样(因为那太可怕了)
  • @gvlasov 好点,但是如何从子接口访问父接口的默认方法,有可能吗?更新............是的可能,更具体的解释在这里stackoverflow.com/a/24280376/3791156
  • @RichardTingle 完美回答!
  • @tejasvi88 Interface.method() 将暗示Interface 中的静态方法。这是一种“超级”,所以超级部分可以说是最重要的
【解决方案2】:

下面的代码应该可以工作。

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

【讨论】:

  • 我认为这是描述上述问题的最佳示例。谢谢
【解决方案3】:

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

Java 8 接口引入了多重继承的某些方面。默认方法具有已实现的函数体。要从超类调用方法,可以使用关键字super,但如果要使用超接口进行调用,则需要显式命名。

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

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

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

public class Example extends ParentClass implements InterfaceFoo, InterfaceBar {
    public void hello() {
        super.hello(); // (note: ParentClass.super could not be used)
        InterfaceFoo.super.hello();
        InterfaceBar.super.hello();
    }
    
    public static void main(String[] args) {
        new Example().hello();
    }
}

输出:

你好家长班!
你好 InterfaceFoo!
界面栏你好!

【讨论】:

    【解决方案4】:

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

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

    输出:

    A.foo

    【讨论】:

    • OP 说:“当方法被覆盖时,[是否]可以显式调用该方法的默认实现”
    【解决方案5】:

    是否要覆盖接口的默认方法取决于您的选择。因为 default 类似于类的实例方法,可以直接在实现类对象上调用。 (简而言之,接口的默认方法是由实现类继承的)

    【讨论】:

      【解决方案6】:

      考虑以下示例:

      interface I{
          default void print(){
          System.out.println("Interface");
          }
      }
      
      abstract class Abs{
          public void print(){
              System.out.println("Abstract");
          }
      
      }
      
      public class Test extends Abs implements I{
      
          public static void main(String[] args) throws ExecutionException, InterruptedException 
          {
      
              Test t = new Test();
              t.print();// calls Abstract's print method and How to call interface's defaut method?
           }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-02-09
        • 2018-06-13
        • 2016-10-15
        • 1970-01-01
        • 2019-03-03
        • 1970-01-01
        相关资源
        最近更新 更多