Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multilevel static nested class producing wrong output

When following code is run it prints "X.Q" instead of "A<T>.X.Q" as required by the language specification.

    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();
    }
}

Can some one help me understand what will be the output of this program, as per my understanding it should be "A<T>.X.Q" instead of "X.Q" , Please correct me if i am mistaken some where

like image 753
Sachin Sachdeva Avatar asked May 08 '17 16:05

Sachin Sachdeva


2 Answers

The reason that you are getting "X.Q" printed is that X refers to the class X scoped to the unnamed package, not A<T>.X. It does not matter that "outside" X is declared after B, because Java compiler sees it before resolving the name of B.Y's base class.

You can force inheritance from A.X in your code as follows:

class B extends A<B.Y.Q> {
    static class Y extends A.X {
    } //                   ^^
      //                Add this
}

Demo 1.

Edit: (thanks user695022 for the comment)

Curiously, the problem goes away if the outer class is not generic:

class A {
    static class X {
        static class Q {
            public static void main() {
                System.out.println("A<T>.X.Q");
            }
        }
    }
}

Demo 2.

like image 65
Sergey Kalinichenko Avatar answered Nov 16 '22 20:11

Sergey Kalinichenko


Okay, lets see what you have here. As per my understanding, your argument is basically about Y extends X but which X. The access by defaults to the outer scope. If you delete the outer X, it won't compile because X is not available. For inner static classes, you will have to either put explicit import statement or reference it with fully qualified name while extending.

It is the default convention in resolution. This also makes sense if you realize that there can only be 1 class with the same name within the outer scope but you can have many inner static classes with the same name. You need a convention for access for all of these. This convention solves it in a seemingly intuitive manner(otherwise, you would have to type fully qualified name for all the X's while extending)

If you consider the outer one, it should print, "X.Q" which it does.

like image 2
Manish Kumar Sharma Avatar answered Nov 16 '22 21:11

Manish Kumar Sharma