问题
I have:
public class A implements BListener {
public interface AListener {}
}
public class B implements AListener {
public interface BListener {}
}
So, if I understand correctly the cyclic inheritance happens because:
The compiler goes to A and says "hey, A implements BListener, let's go find BListener!"
Then when it tries to find BListener, it eventually gets to B, which it says:
"Hey, BListener, needed for A is inside B! BUT WAIT! B needs AListener! Let's go find AListener!"
And then it gets to A, repeat. Did I get this right?
By the way, this compilation error happened to me on Android development.
回答1:
It may help to draw it out.
>A
is part of / \ inherits
V
AListener BListener
^
inherits \ / is part of
B<
A lovely circle. You can't create one of them without the others already existing.
Is the compiler a squirrel with ADHD high on coffee chasing it's own tail?
Nope because a the squirrel would not stop (until the caffeine ran out). The compiler looks for this and then gives up.
Note: Eclipse has a bug which allows this setup.
回答2:
After further investigation, I was initially wrong.
The technical explanation for the behavior you are noticing is the following
From the Java Language Specification chapter on Superclasses and subclasses
A class
C
directly depends on a typeT
ifT
is mentioned in theextends
orimplements
clause ofC
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 typeT
if any of the following is true:
C
directly depends onT
.C
directly depends on an interfaceI
that depends (§9.1.3) onT
.C
directly depends on a classD
that depends onT
(using this definition recursively).It is a compile-time error if a class depends on itself.
Let's take your code, with fully qualified names for type uses, assuming the classes were declared in package com.example
:
public class A implements com.example.B.BListener {
public interface AListener {}
}
public class B implements com.example.A.AListener {
public interface BListener {}
}
Following the rules from the JLS above
A
directly depends onBListener
, because it's mentioned in itsimplements
clause.A
directly depends onB
, because it's mentioned as a qualifier in the fully qualified name of a superinterface (BListener
iscom.example.B.BListener
)B
directly depends onAListener
, because it's mentioned in itsimplements
clause.B
directly depends onA
, because it's mentioned as a qualifier in the fully qualified name of a superinterface (AListener
iscom.example.A.AListener
)A
directly depends onB
that depends onA
.
Therefore A
depends on A
and a compilation error should occur.
In Eclipse, the error occurs if you qualify the names
class A implements B.BListener {
public static interface AListener {
}
}
class B implements A.AListener {
public static interface BListener {
}
}
If you use import
statements, however, it doesn't. I'll be opening a bug with them.
来源:https://stackoverflow.com/questions/33918022/cyclic-inheritance-and-interfaces-class-a-cant-implement-class-b-interface-wh