循环继承和接口 - class A 不能实现 class B 接口,而 class B 实现 A 接口

Cyclic inheritance and interfaces - class A can't implement class B interface while class B implements A interface

我有:

public class A implements BListener {
    public interface AListener {}
}

public class B implements AListener {
    public interface BListener {}
}

所以,如果我理解正确的话,循环继承的发生是因为:

编译器转到 A 并说 "hey, A implements BListener, let's go find BListener!"

然后当它试图找到 BListener 时,它最终到达 B,它说:

"Hey, BListener, needed for A is inside B! BUT WAIT! B needs AListener! Let's go find AListener!"

然后到达A,重复。我做对了吗?

顺便说一句,这个编译错误发生在我身上 Android 开发。

画出来可能会有帮助。

              >A 
is part of  /     \    inherits
                   V             
   AListener        BListener
           ^
  inherits  \     /    is part of 
               B<

一个可爱的圆圈。如果没有其他已经存在的,你不能创建其中之一。

Is the compiler a squirrel with ADHD high on coffee chasing it's own tail?

不,因为松鼠不会停止(直到咖啡因 运行 消失)。编译器寻找它然后放弃。

注意:Eclipse 有一个允许此设置的错误。

经过进一步调查,我最初是错的。

您注意到的行为的技术解释如下

来自 Java 语言规范章节 Superclasses and subclasses

A class C directly depends on a type T if T is mentioned in the extends or implements clause of C either as a superclass or superinterface, or as a qualifier in the fully qualified form of a superclass or superinterface name.

A class C depends on a reference type T if any of the following is true:

  • C directly depends on T.
  • C directly depends on an interface I that depends (§9.1.3) on T.
  • C directly depends on a class D that depends on T (using this definition recursively).

It is a compile-time error if a class depends on itself.

假设 类 是在 com.example 包中声明的:

public class A implements com.example.B.BListener {
    public interface AListener {}
}

public class B implements com.example.A.AListener {
    public interface BListener {}
}

遵循上述 JLS 的规则

  • A 直接依赖于 BListener,因为它在其 implements 子句中被提及。
  • A 直接依赖于 B,因为它在超级接口的完全限定名称中作为限定符被提及(BListenercom.example.B.BListener
  • B 直接依赖于 AListener,因为它在其 implements 子句中被提及。
  • B 直接依赖于 A,因为它在超级接口的完全限定名称中作为限定符被提及(AListenercom.example.A.AListener
  • A直接依赖B又依赖A.

因此A依赖于A,应该会出现编译错误。


在 Eclipse 中,如果您限定名称,则会出现错误

class A implements B.BListener {
    public static interface AListener {
    }
}

class B implements A.AListener {
    public static interface BListener {
    }
}

但是,如果您使用 import 语句,则不会。我将与他们一起打开一个错误。