Programmingfreak
Programmingfreak

Reputation: 61

superclass with private static field and subclass calls a method that changes the field, Why doesn't the field change?

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();
}

Why does the program print true instead of false, I don't understand why goo didn't change after foo() was called. goo isn't hidden because it is a private field. the static field before creating an object is true, then when foo occurs isn't it supposed to change goo in Heap?

Upvotes: -3

Views: 279

Answers (2)

AxelH
AxelH

Reputation: 14572

The reason is well explained inPanz0r's answer but what you don't see is that you have two variable call bar, one in A one in B.

If you add a method to print the instance members in both class (and A will also print is super class):

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;
    }
}

You will see that both bar exist in an instance A

Base:false
Sub:true

You could access B.bar variable using super.bar if the accessibility allowed it but it is private in your case.

A solution would be to use a constuctor B that will accept a value and concatenate the result of foo.

public String bar;

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

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

And in A

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

Only the creation of B will call foo so you get the result :

Sub: false

Let's check with this :

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

Sub: false
Base: true
Sub: false

Upvotes: 2

Panz0r
Panz0r

Reputation: 105

Because you change the value twice?

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

Upvotes: 3

Related Questions