两个具有相同方法名称和签名的接口。但是由单个类实现那么编译器将如何识别哪个方法是为哪个接口?

Ex:

interface A{
  int f();
}

interface B{
  int f();
}

class Test implements A, B{   
  public static void main(String... args) throws Exception{   

  }

  @Override
  public int f() {  // from which interface A or B
    return 0;
  }
}   

当前回答

在接口中,我们只是声明方法,实现这两个接口的具体类理解的是只有一个方法(正如你所描述的在返回类型中有相同的名称)。所以应该不会有什么问题。您将能够在具体类中定义该方法。

但是当两个接口有相同名称但不同返回类型的方法时,你在具体类中实现了两个方法:

请看下面的代码:

public interface InterfaceA {
  public void print();
}


public interface InterfaceB {
  public int print();
}

public class ClassAB implements InterfaceA, InterfaceB {
  public void print()
  {
    System.out.println("Inside InterfaceA");
  }
  public int print()
  {
    System.out.println("Inside InterfaceB");
    return 5;
  }
}

当编译器获得方法“public void print()”时,它首先在InterfaceA中查找并获得它。但是它仍然给出编译时错误,返回类型与InterfaceB的方法不兼容。

所以编译器就乱套了。

通过这种方式,您将无法实现两个具有相同名称但返回类型不同的方法的接口。

其他回答

如果它们都是一样的,那就无所谓了。它通过每个接口方法一个具体的方法来实现这两种方法。

这被标记为这个问题https://stackoverflow.com/questions/24401064/understanding-and-solving-the-diamond-problems-in-java的重复

您需要Java 8来得到一个多重继承问题,但它仍然不是一个diamon问题。

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

interface B {
    default void hi() { System.out.println("B"); }
}

class AB implements A, B { // won't compile
}

new AB().hi(); // won't compile.

正如JB Nizet评论的那样,你可以修复我的重写。

class AB implements A, B {
    public void hi() { A.super.hi(); }
}

但是,你对

interface D extends A { }

interface E extends A { }

interface F extends A {
    default void hi() { System.out.println("F"); }
}

class DE implement D, E { }

new DE().hi(); // prints A

class DEF implement D, E, F { }

new DEF().hi(); // prints F as it is closer in the heirarchy than A.

就编译器而言,这两个方法是相同的。两者都将有一个实现。

如果这两个方法实际上是相同的,这就不是问题,因为它们应该有相同的实现。如果它们在合同上是不同的(根据每个接口的文档),那么您就有麻烦了。

还可以采用以下两种方法来实现重复的方法并避免歧义-

方法1:

App.java -

public class App {
    public static void main(String[] args) {
        TestInterface1 testInterface1 = new TestInterface1();
        TestInterface2 testInterface2 = new TestInterface2();
        testInterface1.draw();
        testInterface2.draw();
    }
}

TestInterface1.java -

public class TestInterface1 implements Circle {
    
}

TestInterface2.java -

public class TestInterface2 implements Rectangle {
    
}

Circle.java -

public interface Circle extends Drawable {
    @Override
    default void draw() {
        System.out.println("Drawing circle");
    }
}

Rectangle.java -

public interface Rectangle extends Drawable {
    @Override
    default void draw() {
        System.out.println("Drawing rectangle");
    }
}

Drawable.java -

public interface Drawable {
    default void draw() {
        System.out.println("Drawing");
    }
}

输出-

Drawing circle
Drawing rectangle

方法2:

App.java -

public class App {
    public static void main(String[] args) {
        
        Circle circle = new Circle() {
                
        };
        Rectangle rectangle = new Rectangle() {
                
        };

        circle.draw();
        rectangle.draw();
    }
}

Circle.java -

public interface Circle extends Drawable {
    @Override
    default void draw() {
        System.out.println("Drawing circle");
    }
}

Rectangle.java -

public interface Rectangle extends Drawable {
    @Override
    default void draw() {
        System.out.println("Drawing rectangle");
    }
}

Drawable.java -

public interface Drawable {
    default void draw() {
        System.out.println("Drawing");
    }
}

输出-

Drawing circle
Drawing rectangle

没有什么可识别的。接口只禁止方法名和签名。如果两个接口的方法名称和签名完全相同,实现类可以用一个具体方法实现两个接口方法。

然而,如果这两个接口方法的语义契约是矛盾的,那么你就输了;这样你就不能在一个类中实现两个接口。