views:

217

answers:

5

While studying for the SCJP 6 exam, I ran into this question in a test exam:

class A{  
    private static String staticProperty = " a ";  
    String getStaticProperty() { return staticProperty; }  
}  

class B extends A {  
    private static String staticProperty = " b ";  
    public static void main(String[] args){  
        new B().go(new A());  

    }  
    void go(A t){  
        String s = t.getStaticProperty() + B.staticProperty + staticProperty + (new B().getStaticProperty());  
        System.out.println(s);  
    }  
}

What's the output??

The output here is a b b a

I perfectly understand a b b, but don't understand the "a" at the end. If you inherit a method (in this case, B inherits getStaticProperty() from A), and that method returns a static variable from the parent (staticProperty), which you re-define in the child, you will ALWAYS use the parent static variable value??

By the way, removing the static identifier and making staticField an instance member of the classes returns the same results. Modifying access modifiers from private to public or other returns the same results. I needed to override the getStaticProperty method in order to get what I wanted to see.

+3  A: 

new B().getStaticProperty() is calling the method from A which returns A's static property because it's scoped to A.

Mark E
A: 

getStaticProperty() is a method defined on class A. The method is not overriden on class B, therefore the method from class A is used. Since A cannot 'see' B's static property in any way, it returns it's own value.

+1  A: 

Functions are virtual in Java, but class members (static or instance) are not. So while B's definition of staticProperty may mask A's definition, it doesn't override it.

// in B
String fromChild = staticProperty; // == "b"
String fromParent = A.staticProperty; // == "a", was masked but not overridden

The only way to get A to access a variable defined in B is to define a getter function in A and override it in B, as you suggest.

Michael Brewer-Davis
So even when B inherits the getStaticProperty() method from A (and in consequence, if would be as if B declared it itself), this inherited method is still referencing the property from the superclass?I see the conflict with the member name. Perhaps if staticProperty in B had a different name, things would be easier to see.
Dan
+4  A: 

Field access is not subject to dynamic dispatch like method access, i.e. fields cannot be overriden. This line in class A:

String getStaticProperty() { return staticProperty; }

therefore refers to the field staticProperty in class A. Class B's field with the same name is irrelevant, or rather: it hides the superclass field, and all code in class B will use this field. Sun's Java tutorial has this to say on the matter:

Within a class, a field that has the same name as a field in the superclass hides the superclass's field, even if their types are different. Within the subclass, the field in the superclass cannot be referenced by its simple name. Instead, the field must be accessed through super, which is covered in the next section. Generally speaking, we don't recommend hiding fields as it makes code difficult to read.

Michael Borgwardt
+1  A: 

When thinking about inheritance issues such as this one, you may find it helpful to think about what happens when new B() is invoked. When B's constructor executes, the first operation it performs (since since there is no explicit call to A's constructor) is super(). At this point an instance of A is created, and in this object the getStaticProperty() method clearly refers to A's staticProperty. The body of B's constructor then runs (again, only after successful execution of A's constructor), and as it does nothing to alter or override the getStaticProperty() method that was instantiated by A's constructor it certainly doesn't change the behavior of that method either.

This may seem confusing initially, but it can be a helpful way to think through the implications of various inheritance issues.

Shaun
This is a really well written answer to the question. Shaun is right - the call to super is key here.
Shaun F