14

While exploring for scjp questions, I came across this behaviour which I found strange.

I have declared two classes Item and Bolt as follows:

class Item {
    int cost = 20;

    public int getCost() {
        return cost;
    }
}

class Bolt extends Item {
    int cost = 10;

    public int getCost() {
        return cost;
    }
}

and tried to access the value of cost twice

public class Test {
    public static void main(String[] args) {
        Item obj = new Bolt();
        System.out.println(obj.cost);
        System.out.println(obj.getCost());
    }
}

The output I get is 20 10. I can't understand how this happens.

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
santosh-patil
  • 1,540
  • 1
  • 15
  • 29
  • No. @Override is only an indication to the compiler that you want this method to override another one, and that it should produce an error if it's not the case. But as soon as the methods have the same signature, the second one is overriding the first one. Annotations didn't exist before Java 5. – JB Nizet Aug 02 '11 at 07:12
  • @netbrain, getCost method of subclass works fine. I was curious about result of directly calling obj.cost. But as Sanjay says it's due to the fact that runtime polymorphism is applicable to only methods not fields. – santosh-patil Aug 02 '11 at 07:13

2 Answers2

19

obj is a reference of type Item hence the first 20 since the value of cost field of Item is 20. The second value is 10 because the runtime type of obj is Bolt and hence getCost() invokes getCost of Bolt class (since Bolt extends Item).

In short, runtime polymorphism is applicable to only instance members (method overriding) and not instance fields.

Sanjay T. Sharma
  • 22,857
  • 4
  • 59
  • 71
  • So there are two cost fields in a Bolt object? – bcr Aug 02 '11 at 07:08
  • From an implementation detail perspective, only *one* object is created when you say `new Bolt()`. But yes, the subclass is pretty much aware of the fields/methods its super-class hosts. You can verify this by adding a third `sysout` in your code: `System.out.println(((Bolt)obj).cost)` – Sanjay T. Sharma Aug 02 '11 at 07:11
  • @Sanjay, though I have not created any object of Item class, still it prints the value defined in Item class. That's what I found strange. – santosh-patil Aug 02 '11 at 07:17
7

Class fields do not participate in polymorphism game. The methods do.

So, when you access the field you go to one that is defined in base class because you object's type is Item. When you call method you get the actual value because you invoke method using polymorphism.

Conclusion:

Fields are always private. If you want to access field write method.

AlexR
  • 114,158
  • 16
  • 130
  • 208