产生错误输出的多级静态嵌套类
Posted
技术标签:
【中文标题】产生错误输出的多级静态嵌套类【英文标题】:Multilevel static nested class producing wrong output 【发布时间】:2017-05-08 16:26:20 【问题描述】:运行以下代码时,它会按照语言规范的要求打印 "X.Q"
而不是 "A<T>.X.Q"
。
class A<T>
static class X
static class Q
public static void main()
System.out.println("A<T>.X.Q");
class B extends A<B.Y.Q>
static class Y extends X
// X here is inherited from A
class X
static class Q
public static void main()
System.out.println("X.Q");
public class Test
public static void main(String[] args)
B.Y.Q.main();
谁能帮我理解这个程序的输出是什么,根据我的理解应该是"A<T>.X.Q"
而不是"X.Q"
,如果我在哪里弄错了,请纠正我
【问题讨论】:
是不是看不到主类名为Test的代码sn-p 对不起,我读得太快了。 没关系..请检查代码并分享您的想法... :) 它应该打印“AX
,一个来自外部范围,一个来自内部A<T>
。当编译器解析名称时,来自外部范围的X
“获胜”。
【参考方案1】:
打印"X.Q"
的原因是X
指的是类X
,其作用域为未命名的包,而不是A<T>.X
。在B
之后声明“外部”X
并不重要,因为 Java 编译器在解析 B.Y
的基类名称之前会看到它。
您可以在代码中强制继承 A.X
,如下所示:
class B extends A<B.Y.Q>
static class Y extends A.X
// ^^
// Add this
Demo 1.
编辑:(感谢user695022的评论)
奇怪的是,如果外部类不是通用的,问题就会消失:
class A
static class X
static class Q
public static void main()
System.out.println("A<T>.X.Q");
Demo 2.
【讨论】:
这不是真的。没有泛型,即使你只写 X,Y 也会扩展 A.X。在这里,我分叉了你的演示:ideone.com/JUoUaU @user695022 感谢演示,我编辑了答案以包含它。 @user695022 :这很有趣,因为继承确实在解析中起作用。这根本不直观。谢谢。【参考方案2】:好的,让我们看看你有什么。根据我的理解,您的论点基本上是关于Y extends X
,但是X
。默认情况下访问外部范围。如果删除外部的X
,它将无法编译,因为X
不可用。对于内部静态类,您必须在扩展时放置显式导入语句或使用完全限定名称引用它。
这是分辨率的默认约定。这也是有意义的如果您意识到在外部范围内只能有 1 个具有相同名称的类,但您可以有许多具有相同名称的内部静态类。您需要一个所有人都可以访问的约定这些。这个约定以一种看似直观的方式解决了它(否则,您必须在扩展时为所有 X
键入完全限定名称)
如果你考虑外部的,它应该打印,"X.Q"
它确实如此。
【讨论】:
【参考方案3】:Q 的 main 方法,打印 X.Q 是被调用的方法,因为 B.Y 扩展了 X(不是 A.X),其 Q 方法隐藏了 A.X.Q.main 方法。
后续有点糊涂,简单的添加trace或者一步步调试就可以看到完整的调用树了。
【讨论】:
以上是关于产生错误输出的多级静态嵌套类的主要内容,如果未能解决你的问题,请参考以下文章