规定在Java中继承静态变量的规则是什么?

jmg*_*sen 45 java inheritance

我有一节课,Super:

public class Super {
    public static String foo = "foo";
}
Run Code Online (Sandbox Code Playgroud)

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

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

    public static void main (String[] args) {
        System.out.println(Super.foo);
    }
}
Run Code Online (Sandbox Code Playgroud)

当我运行它时,它打印出来bar.
我的第三个(也是最后一个)课程是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);
    }
}
Run Code Online (Sandbox Code Playgroud)

这打印:

foo
foo
foo
Run Code Online (Sandbox Code Playgroud)

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

Jon*_*eet 43

我不明白为什么foo的内容取决于你从哪个类访问它.

基本上这是类型初始化的问题.的值foo设置为"bar"Sub被初始化.但是,在您的Testing类中,引用Sub.foo实际上被编译为引用Super.foo,因此它不会最终初始化Sub,因此foo永远不会变为"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);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后它将打印出"bar"四次,因为第一个语句将强制Sub初始化,这将改变值foo.这根本不是它从哪里进入的问题.

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

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

那仍然会打印"foo"两次,显示它Sub没有被初始化 - 但是它肯定被加载了,例如,如果你Sub.class在运行之前删除文件,程序将会失败.

  • @jmgrosen:是的 - 因为只有一个变量,由`Super`声明.正如maerics所说,它可以通过"Sub"访问,但这并不意味着它是一个不同的变量. (4认同)
  • 这似乎是正确的,但你碰巧知道为什么`Sub.foo`编译成`Super.foo`? (2认同)
  • @PrashantShilimkar:我不确定你要问的是什么,说实话......最后一个成员只能分配一次. (2认同)
  • "基本上它是类型初始化的问题"不是真的,这是类加载的问题.加载类时运行静态块,第一个实例化(或调用静态方法)是加载类的原因 (2认同)