在Java中,有哪些规则决定了静态变量的继承?

2022-08-31 21:04:29

我有一个类, :Super

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

我还有另一个类,它扩展了:SubSuper

public class Sub extends Super {
    static {
        foo = "bar";
    }

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

当我运行它时,它会打印出来。
我的第三堂(也是最后一堂)课是:barTesting

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

这打印:

foo
foo
foo

我不明白为什么的内容会有所不同,具体取决于您从哪个类访问它。谁能解释一下?foo


答案 1

我不明白为什么foo的内容会有所不同,具体取决于您从哪个类访问它。

基本上,这是一个类型初始化的问题。的值设置为初始化时间。但是,在您的类中,对 的引用实际上被编译为对 的引用,因此它最终不会初始化,因此永远不会变成 。foo"bar"SubTestingSub.fooSuper.fooSubfoo"bar"

如果将测试代码更改为:

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

然后它会打印出“bar”四次,因为第一个语句将强制初始化,这将更改 的值。这根本不是从哪里访问它的问题。Subfoo

请注意,这不仅仅是关于类加载 - 而是关于类初始化。可以在不初始化的情况下加载类。例如:

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

这仍然打印“foo”两次,表明它未初始化 - 但它肯定已加载,例如,如果您在运行文件之前删除该文件,程序将失败。SubSub.class


答案 2

在何处更改静态变量的值并不重要,它是相同的可变变量 foo、in 或 。创建多少个对象,然后修改,这都无关紧要。这种变化随处可见,因为 、 共享同一块存储。这也适用于基元类型:SubSupernew Subnew SuperSuper.fooSub.fooobj.foo

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

您可以通过对象(如 )或通过其类名(如 )引用静态变量/方法。最好使用 来强调变量/方法的静态性质,并为编译器提供更好的优化机会。sc.aStaticParent.aClassName.staticVariable


推荐