动态绑定,覆盖

dynamic binding, overriding

public class Base {
    private static boolean goo = true;
    protected static boolean foo() {
          goo = !goo;
          return goo;
    }

    public String bar = "Base:" + foo();

    public static void main(String[] args) {
         Base base = new Sub();
         System.out.println("Base:"+ base.foo());
    }
}

public class Sub extends Base {
    public String bar = "Sub:" + foo();
    protected static boolean foo() {
        return false;
    }
}

为什么输出是"Base: true"? foo() 似乎是一个覆盖方法,所以动态类型是 Sub,而不是为什么 return 输出不是 "false",而且 Base 的字段有一个字符串,不应该有它的输出?

在java中,你不能覆盖静态方法,如果你在子class中重新定义super class方法的那个静态方法,那么它就变成方法覆盖(方法隐藏),而不是覆盖。

在您的示例中,您使用 super class ref(base) 调用它,因此仅调用 super class 方法而不调用 sub class 方法。所以输出是 "Base: true"

如果您使用非静态方法更改它,那么子 class 方法将被执行。

这里的规则是:super class ref 和 sub class 对象将适用于非静态方法。

方法覆盖用于覆盖子对象的行为class,不适用于静态方法。没有理由为静态方法支持此功能。此外,您不需要创建对象来访问静态方法。您可以简单地通过其名称[foo()] 或使用class名称作为前缀来引用它[例如:Sub.foo()].

就输出中返回 true 的原因而言,这是因为您已经在 class 中使用了以下语句,它调用了 foo() 方法

public String bar = "Base:" + foo();

因为 goo 是一个静态变量,所以只为这个 class 维护这个变量的一个实例。并且在执行上述语句时,goo 的值变为 false(goo=!goo,goo 最初为 true)。

稍后,当您使用 base.foo() 时,基础 class 的 foo() 将被执行 [因为方法覆盖不适用于静态方法和Base class reference is being used] 再次恢复 goo 的值使其为真。

当您在方法或变量方面处理单词 "static" 时,它指的是该方法或变量属于 "class" 而不是其对象。

当没有对象时,就没有覆盖。

在您的 class Base 中,您声明了 main() 方法,您在其中编写了以下语句。

Base base = new Sub();
System.out.println("Base:"+ base.foo());

现在,引用变量类型为Base,对象类型为Sub。由于 foo() 是一个静态方法,它属于声明引用变量的 class (即 基础)。 因此,foo方法classBase 被调用。