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

时间:2012-03-27 21:37:22

标签: java inheritance

我有一个班级Super

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

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

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

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

当我运行它时,会打印出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);
    }
}

打印:

foo
foo
foo

我不明白为什么foo的内容会因您访问它的类而有所不同。谁能解释一下?

3 个答案:

答案 0 :(得分:42)

  

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

基本上这是类型初始化的问题。初始化foo时,"bar"的值设置为Sub。但是,在Testing课程中,对Sub.foo的引用实际上已编译为对Super.foo的引用,因此它不会最终初始化Sub,因此{{1永远不会成为foo

如果您将测试代码更改为:

"bar"

然后它将打印出“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); } } 被初始化,这会改变Sub的值。这根本不是从哪里进入的。

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

foo

仍然打印“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); } } 未初始化 - 但它肯定是已加载,如果删除Sub文件,程序将失败例如,在运行它之前。

答案 1 :(得分:0)

在哪里更改静态变量的值并不重要,它与SubSuper中的变量foo相同。无论您创建并修改了多少new Subnew Super个对象,都无关紧要。由于Super.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.a)或通过其类名(如StaticParent.a)引用静态变量/方法。最好使用ClassName.staticVariable来强调变量/方法的静态性质,并为编译器提供更好的优化机会。

答案 2 :(得分:-3)

静态成员不是在java中继承的,因为它们是类的属性,并且它们在类区域中加载。它们与对象创建无关。但是只有子类可以访问其父类的静态成员。