背景

这篇文章作为上一篇文章JAVA: 子类“覆盖”父类的成员变量的补充,主要说明子类通过static块“覆盖”父类成员变量时的一个潜在风险。

例子

先来看个例子,关于通过static块“覆盖”父类成员变量的情况

public class Person {
    public static String name = "person";
}

public class Dad extends Person {
    static {
        name = "Dad";
    }
}

public class Mom extends Person {
    static {
        name = "Mom";
    }
}

public static void main(String[] args) {
    System.out.println(Person.name);
    System.out.println(Dad.name);
    System.out.println(Mom.name);
    Person dad = new Dad();
    System.out.println(Person.name);
    System.out.println(Dad.name);
    System.out.println(Mom.name);
    Person mom = new Mom();
    System.out.println(Person.name);
    System.out.println(Dad.name);
    System.out.println(Mom.name);
}

输出结果为:

person
person
person
Dad
Dad
Dad
Mom
Mom
Mom

分析

如果单单只看这个简单例子,从static的含义来说,问题很清楚;因为static变量namePerson类是否实例化无关,当改变name值时会使得所有的Person类及其子类,以及实例中name值都发生变化,即name是共享的。

static块会在类初始化时执行,并且整个程序运行过程中只执行一次,而static块中对name值的修改就会在初始化时发生。所以例子中在Dad类初始化时会修改nameDadMom类初始化时会修改nameMom,而在Person类及其子类中name值都相同。

潜在风险

应当注意在某个类有多个子类时,子类对父类的static成员变量是共享的,拿父类static成员变量存储本子类独有的数据时,很可能引发错误。

参考