DK_bhai
DK_bhai

Reputation: 359

Why can't I access an inner static class in java with class object

When I access a static member with instance of class it works, then why error with static inner class?
In C++ we can access static members with instance as well the class name.
How is it different in Java.

class OuterClass{
    static public int x;
    public static void show(){
        System.out.println(x);
    }
    public static class InnerClass{
        static public int y;
    }
}

public class MyApp {
    public static void main(String[] args){
        OuterClass obj = new OuterClass();
        obj.x= 5;
        System.out.println(obj.x);   // This runs fine 
        obj.InnerClass.y = 10;       // Error
        System.out.println(obj.InnerClass.y);
        OuterClass.InnerClass.y=10;  // This works why ?
        System.out.println(OuterClass.InnerClass.y);
    }
}

My apologies if this is a stupid question, new to Java hope you understand.
Regards

Upvotes: 1

Views: 686

Answers (1)

rzwitserloot
rzwitserloot

Reputation: 102822

obj.x = 5; System.out.println(obj.x);

Yes, this works, but 'by accident'. The java language spec allows this, but note that every linting tool out there, and the current core engineering team of java, will all tell you that this is bad code style and you should not do this.

When in rome, be like the romans: If you prefer this code style, that's... immaterial. Don't write this. You're not in your own little bubble, you read the code that others write, and others will read and work with the code you write.

The only reason this is still allowed in java is because java doesn't like to break backwards compatibility.

The reason it's nuts is that someExpr.someThing rather strongly suggests that someExpr is in any way or form relevant. As in, that, at runtime, someExpr is evaluated and whatever object it points at (remember, in java, all variables except primitives are like C pointers, but in java we call them references. Potayto Potahto) is then used to either fetch that field or invoke that method.

But that is not what happens if someThing is a static concept: For a trivial proof of this, make someExpr null and note how that still just works (no NullPointerException is thrown), thus proving no dereferencing is taking place.

That's confusing. If someThing is static, then it belongs to the class and not any particular instance of it, so write it like that: OuterClass.x.

obj.InnerClass.y = 10; System.out.println(obj.InnerClass.y);

Yes, error. Whilst you can refer to static methods and static fields by writing x.fieldOrMethod where x is an expression whose static (compile-time, not runtime) type is a type that has fieldOrMethod as field or method member, it works, but not if that is an inner type. Why? Because the java spec says so.

Note that inner types were added in java 1.1, and I'm pretty sure the lang team already realized that allowing obj.staticThing was a design mistake, so they intentionally decided not to expand on and prolong that mistake. It is further fuel on the fire as to why you should not make a habit out of this style; it doesn't consistently work.

OuterClass.InnerClass.y=10; System.out.println(OuterClass.InnerClass.y);

Finally we get to proper code. Not just that it works, but this is how you should be doing it. OuterClass.InnerClass is the name of InnerClass: All classes are in effect 'static' when referring to just the class: It's not that there is one variant of InnerClass for each instance of OuterClass (not even if InnerClass is non-static): The concept "InnerClass" only exists once. There is only one instance of java.lang.Class<?> to represent "InnerClass", whether InnerClass is static or not. What other way would yourefer to InnerClass? obj.InnerClass makes zero sense - referring to InnerClass does not require an instance of obj - it is weird to supply irrelevant and unused information (in this case, the obj reference).

Upvotes: 2

Related Questions