What are the rules dictating the inheritance of static variables in Java?

JavaInheritance

Java Problem Overview


I have a class, Super:

public class Super {
    public static String foo = "foo";
}

I also have another class, Sub that extends Super:

public class Sub extends Super {
    static {
        foo = "bar";
    }
    
    public static void main (String[] args) {
        System.out.println(Super.foo);
    }
}

When I run it, it prints out bar.
My third (and last) class is Testing:

public class Testing {
    public static void main (String[] args) {
        System.out.println(Super.foo);
        System.out.println(Sub.foo);
        System.out.println(Super.foo);
    }
}

This prints:

foo
foo
foo

I don't understand why the contents of foo vary depending on what class you're accessing it from. Can anyone explain?

Java Solutions


Solution 1 - Java

> I don't understand why the contents of foo vary depending on what class you're accessing it from.

Basically it's a matter of type initialization. The value of foo is set to "bar" when Sub is initialized. However, in your Testing class, the reference to Sub.foo is actually compiled into a reference to Super.foo, so it doesn't end up initializing Sub, so foo never becomes "bar".

If you change your Testing code to:

public class Testing {
    public static void main (String[] args) {
        Sub.main(args);
        System.out.println(Super.foo);
        System.out.println(Sub.foo);
        System.out.println(Super.foo);
    }
}

Then it would print out "bar" four times, because the first statement would force Sub to be initialized, which would change the value of foo. It's not a matter of where it's accessed from at all.

Note that this isn't just about class loading - it's about class initialization. Classes can be loaded without being initialized. For example:

public class Testing {
    public static void main (String[] args) {
        System.out.println(Super.foo);
        System.out.println(Sub.class);
        System.out.println(Super.foo);
    }
}

That still prints "foo" twice, showing that Sub isn't initialized - but it's definitely loaded, and the program will fail if you delete the Sub.class file before running it, for example.

Solution 2 - Java

It does not matter where you change value of a static variable, it is the same variabile foo, in Sub or Super. It does not matter neither how many new Sub or new Super objects you create and then modify. The change will be seen everywhere, since Super.foo, Sub.foo, obj.foo share the same piece of storage.This works with primitive types also:

class StaticVariable{
        public static void main(String[] args){
            System.out.println("StaticParent.a = " + StaticParent.a);// a = 2
            System.out.println("StaticChild.a = " + StaticChild.a);// a = 2
            
            StaticParent sp = new StaticParent();
            System.out.println("StaticParent sp = new StaticParent(); sp.a = " + sp.a);// a = 2
            
            StaticChild sc = new StaticChild();
            System.out.println(sc.a);// a = 5
            System.out.println(sp.a);// a = 5
            System.out.println(StaticParent.a);// a = 5
            System.out.println(StaticChild.a);// a = 5
            sp.increment();//result would be the same if we use StaticParent.increment(); or StaticChild.increment();
            System.out.println(sp.a);// a = 6
            System.out.println(sc.a);// a = 6
            System.out.println(StaticParent.a);// a = 6
            System.out.println(StaticChild.a);// a = 6
            sc.increment();
            System.out.println(sc.a);// a = 7
            System.out.println(sp.a);// a = 7
            System.out.println(StaticParent.a);// a = 7
            System.out.println(StaticChild.a);// a = 7
        }
}
class StaticParent{
        static int a = 2;
        static void increment(){
            a++;
        }
}
class StaticChild extends StaticParent{
         static { a = 5;}
}

You can refer to a static variable/method via object (like sc.a) or via it's class name (like StaticParent.a). It is preferable to use the ClassName.staticVariable to emphasize the static nature of the variable/method and to give the compiler better opportunities for optimization.

Solution 3 - Java

Static members are not inherited in java as they are the properties of class and they are loaded in class area. they had nothing to do with object creation. however only the child classes can access the static members of their parent classes.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionjmgrosenView Question on Stackoverflow
Solution 1 - JavaJon SkeetView Answer on Stackoverflow
Solution 2 - JavaDragos PappView Answer on Stackoverflow
Solution 3 - JavaSIKANDARView Answer on Stackoverflow