显然,这样的代码永远不会真正发生。太可怕了。我认为你不应该花太多时间担心它为什么给出 7,但实际上并不难理解为什么。
要评估的第一个字段值是InterfaceA.A
,因此 VM 开始初始化InterfaceA
。这需要InterfaceB.B
,所以它开始初始化InterfaceB
。这需要InterfaceC.C
,所以它开始初始化InterfaceC
。
现在虽然InterfaceC.C
是 引用InterfaceA.A
,但 VM 已经在初始化InterfaceA
,所以不管怎样它都会继续进行(根据JLS 的第 12.4.2 节):
如果 C 的 Class 对象指示当前线程正在对 C 进行初始化,那么这一定是对初始化的递归请求。释放LC并正常完成。
所以InterfaceA.A
仍然是 0(我们仍在尝试计算它应该具有的值,而 0 是 的默认值int
),并InterfaceC.C
得到 1 (0 + 1) 的值。然后InterfaceB.B
得到一个值 2 (1 + 1),InterfaceA.A
得到一个值 4 (2 * 2)。
将所有这些字段值相加,最终得到 7。
如果您使用不同的表达式,您将获得不同的值,因为您会看到最后初始化的不同接口,尽管它仅取决于您引用的第一个字段:
A + B + C = 7 (A = 4, B = 2, C = 1)
A + C + B = 7 (A = 4, B = 2, C = 1)
B + A + C = 3 (A = 0, B = 2, C = 1)
B + C + A = 3 (A = 0, B = 2, C = 1)
C + A + B = 6 (A = 2, B = 1, C = 3)
C + B + A = 6 (A = 2, B = 1, C = 3)
(当然,您必须替换现有的代码行,因为这是关于类型初始化的 - 如果您只添加更多System.out.println
行,您将对上述所有表达式得到相同的答案。)