Lets see how "x.method();" will be evaluated. At compile time we'll first need to determine what class or interface to search for "method()".
Per JLS 15.12.1 - If the form is Primary.NonWildTypeArgumentsopt Identifier, then the name of the method is the Identifier. Let T be the type of the Primary expression; then the class or interface to be searched is T.
Per this, the type of "x" is "ax" & we conclude that we can call "method()" from ax & "x.method()" gets compiled.
Now at runtime, we may think that since Java uses late-binding we'll have to resolve "method()" to use it's runtime type. But that is not the case. Per JLS 18.104.22.168 - If the invocation mode is static, then there is no target reference. The expression Primary is evaluated, but the result is then discarded.
What this means in our case of "x.method()" is that x is evaluated but the result of that evaluation is not used, instead we use the type of "x"
Now lets see how "x1.i" will be evaluated. At compile-time, per JLS 15.12.1(see above), we can only search "ax" for i. Compile fails right away since ax does not have a member i.
Further lets consider what happens if "method()" is an instance method(not static). With "x.method()", again per JLS 15.12.1, we conclude that the class to be searched is "ax".
And now at runtime, something different happens since "method()" is an instance method. Per JLS 22.214.171.124 - the expression Primary is evaluated and the result is used as the target reference.
What that means is we evaluate x which results in a target reference of type "ax" & the method from "ax is called". On the other hand, when we evaluate x1, it results in a target reference of type "bx" & that is why we end up with the method from bx being called.
For reference pleas read the following -
* JLS 15.12.1
* JLS 15.12.4
[ October 03, 2008: Message edited by: Ashish Hareet ]