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

时间:2017-05-08 16:26:21

标签: java inner-classes

当运行以下代码时,它会根据语言规范的要求打印"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",请纠正我,如果我弄错了某些地方

3 个答案:

答案 0 :(得分:5)

您获得"X.Q"打印的原因是X指的是作为未命名包的作用域X,而不是A<T>.X。 &#34;外面&#34;无关紧要。 XB之后被声明为,因为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.

答案 1 :(得分:2)

好的,让我们看看你在这里有什么。根据我的理解,你的论点基本上是Y extends XX。默认情况下访问外部作用域。如果删除外部X,则无法编译,因为X不可用。对于内部静态类,您必须放置显式import语句或在扩展时使用完全限定名称引用它。

这是分辨率的默认约定。如果您意识到在外部作用域中只能有一个具有相同名称的类,但是您可以拥有许多具有相同名称的内部静态类,那么这也是有意义的。您需要一个约定访问所有人这些。此约定以看似直观的方式解决了这个问题(否则,您必须在扩展时键入所有X的完全限定名称)

如果您考虑外部的那个,它应该打印"X.Q"它。

答案 2 :(得分:1)

Q的方法主要打印X.Q是被调用的方法,因为B.Y扩展了X(不是A.X),其Q方法隐藏了A.X.Q.main方法。

跟进起来有点困惑,只需添加跟踪或逐步调试即可看到完整的调用树。