产生错误输出的多级静态嵌套类

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&lt;T&gt;.X.Q"而不是"X.Q",如果我在哪里弄错了,请纠正我

【问题讨论】:

是不是看不到主类名为Test的代码sn-p 对不起,我读得太快了。 没关系..请检查代码并分享您的想法... :) 它应该打印“A.X.Q” @pulp_fiction 那里有两个X,一个来自外部范围,一个来自内部A&lt;T&gt;。当编译器解析名称时,来自外部范围的X“获胜”。 【参考方案1】:

打印"X.Q" 的原因是X 指的是类X,其作用域为未命名的包,而不是A&lt;T&gt;.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或者一步步调试就可以看到完整的调用树了。

【讨论】:

以上是关于产生错误输出的多级静态嵌套类的主要内容,如果未能解决你的问题,请参考以下文章

从嵌套类的函数访问父级的非静态成员

kotlin内部类与嵌套类

kotlin内部类与嵌套类

静态内部类(静态嵌套类或嵌套类)

30根据官方教程详解嵌套类内部类静态嵌套类局部类匿名类 ...

java内部类的静态嵌套类