You're right that Y extends X and that you're overriding method getObject() in Y from X. This method is also called.
By overriding the JVM also calls the method getObject within Y which is the runtime type. This method returns Object B which is a referance to Object A. This method returns 5 from Object A, because polymorphic method invocations apply only to instance methods and not to static methods and variables.
This is one of those tricky things, which is a perfect case of where encapsulation should be used. If you put this code into an IDE, i.e. Eclipse, and throw it in debug mode you will actually see that there are two variables created here... a(a) and a(b). This is because you do not override variables in a subtype, you actually hide them... it's a slightly different concept.
Therefore, you are correct that you get back an object of B(), however your reference variable is of type A. So the program thinks you want the variable from an A object, and gives you the a(a) version. Now, if you actually use getters and setters, you will see that the application will perform more as expected, try this code where I just added comments, and used a getter method instead of trying to directly call the variable:
Dear Keith, I am still not very clear with your explaination. DO you mean to say that an overridden method is called with the prototype of an inherited one? These things are not explained in K&B's book..By going by the book I would definitely go with the answer to be the instance variable(a) of class B and not of class A
Oops..I am in a fix..
Joined: Feb 07, 2005
In some cases, an overridden method has the same return type as the overriding case. So it is clear what method to call.
In all cases, the reference type decides which methods are allowed to be called.
In this example, the reference type is of type X. X only has a method named getObject() with return type A. However, since the overriding class modifies the return type, there is no version of getObject() with return type A in Y. So the compiler adds one that simply acts as a bridge.
When a reference of type X is used to call getObject() on an instance of type Y, then the method with return type A in Y is called. But this method just calls the overridden method getObject().