具有私有静态字段和子类的超类调用更改该字段的方法,为什么该字段没有更改?

时间:2018-07-18 08:07:13

标签: java inheritance field member-hiding

public class B {

    private static  boolean goo=true;

    protected static boolean foo() {
        goo=!goo;
        return goo;
    }

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

    public static void main(String[] args)  {
        B base=new A();
        System.out.println("Base:"+goo);//***prints Base:true***
    }
}

public class A extends B{
    public String bar="Sub:"+foo();
}

为什么程序会打印true而不是false,所以我不明白为什么在调用goo之后foo()没有变化。 goo未隐藏,因为它是一个私有字段。创建对象之前的静态字段为true,那么当发生foo时,是否应该在堆中更改goo

2 个答案:

答案 0 :(得分:3)

因为您两次更改了值?

true -> public String bar="Base:"+foo(); -> false
false -> public String bar="Sub:"+foo(); -> true

答案 1 :(得分:2)

Panz0r's answer中已经很好地解释了原因,但是您看不到您有两个变量调用bar,一个在A中,一个在B中。 / p>

如果您添加了一种方法来打印两个类中的实例成员(并且A也将打印为超类):

public class Main {

    public static void main(String[] args) {
        B base = new A();
        System.out.println(base);
    }
}

class B {

    private static boolean goo = true;

    protected static boolean foo() {
        goo = !goo;
        return goo;
    }

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

    @Override
    public String toString() {
        return bar; //print the variable B.bar
    }
}

class A extends B {
    public String bar = "Sub:" + foo();

    @Override
    public String toString() {
        //print the instance B and the variable A.bar
        return super.toString() + "\n" + bar;
    }
}

您将看到两个bar都存在于实例A

  

Base:false
  子:真

如果可访问性允许,则可以使用B.bar访问super.bar变量,但在您的情况下该变量是私有的。

一种解决方案是使用构造器B,该构造器将接受一个值并连接foo的结果。

public String bar;

public B(){
    this("Base: ");
}

protected B(String source){ //protected to prevent anybody to use it directly
    bar = source + foo();
}

A

public A(){
    super("Sub: ");
}

只有创建B时才会调用foo,这样您就可以得到结果:

  

子:false

让我们检查一下:

System.out.println(new A().bar);
System.out.println(new B().bar);
System.out.println(new A().bar);
  

子:false
  基数:true
  子:假