What are the rules dictating the inheritance of static variables in Java?
JavaInheritanceJava 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.