Java 继承的静态成员的意外行为

Java 继承的静态成员的意外行为,java,inheritance,static,overriding,hide,Java,Inheritance,Static,Overriding,Hide,我只是在玩静态和继承,看看什么可以做,什么不能做。我以前读过,静态方法不能被覆盖,它们可以被隐藏。这就是为什么我试图了解什么适用于静态成员。下面是一些简单的测试代码: public class ParentClass { public static String x; { x = "In ParentClass"; } } public class ChildClass extends ParentClass { { x = "In ChildClass"; } }

我只是在玩
静态
和继承,看看什么可以做,什么不能做。我以前读过,静态方法不能被覆盖,它们可以被隐藏。这就是为什么我试图了解什么适用于静态成员。下面是一些简单的测试代码:

public class ParentClass {
    public static String x;
    { x = "In ParentClass"; }
}

public class ChildClass extends ParentClass {
    { x = "In ChildClass"; }
}
现在,当我打印从对象调用的x时,一切都按预期进行:

ParentClass parentClassReference = new ParentClass();
System.out.println(parentClassReference.x); // prints: "In ParentClass"

parentClassReference = new ChildClass();
System.out.println(parentClassReference.x); // prints: "In ChildClass"
即使是从子类对象对x的简单调用:

ChildClass childClassReference = new ChildClass();
System.out.println(childClassReference.x); // prints: "In ChildClass"
现在,当我调用静态成员时,就像应该做的那样,它变得很奇怪:

System.out.println(ChildClass.x); // prints: "In ChildClass" (Ok, so far.)
System.out.println(ParentClass.x); // prints: "In ChildClass" (This is unexpected.)
我对这种行为没有任何解释。在上下文中,通过对象的调用似乎不应该像预期的那样工作,但是通过类名的调用应该工作

我很困惑。谁能帮忙?

你的代码很奇怪。。。但结果和我预期的完全一样

你需要了解三件事:

  • 这里只有一个
    x
    变量。无论您将其引用为
    ChildClass.x
    还是
    ParentClass.x
    ,它都是相同的变量
  • 当您通过引用引用静态成员时,编译器只是将其转换为静态引用,而根本不查看引用的值。因此
    childClassReference.x
    相当于
    ChildClass.x
    ,实际上编译为
    ParentClass.x
    。好的IDE会警告您这类事情——它会产生令人困惑的代码
  • 您编写的设置
    x
    值的代码仅基于构造函数调用执行。基本上相当于:

    public class ParentClass {
        public static String x;
        public ParentClass() {
            x = "In ParentClass";
        }
    }
    
    public class ChildClass extends ParentClass {
        public ChildClass() {
            x = "In ChildClass";
        }
    }
    

基本上,您不应该试图通过静态成员实现任何类型的多态性。它不起作用,假装它的尝试不会愉快地结束。

好的,现在我看穿了我心中的想法。事实上,我的IDE确实警告过我这一点,但正如我所说:我只是想看看会发生什么。+1 IMHO在构造函数(或初始化程序块)中设置静态字段从来都不是一个好主意