What is the class type of a superclass ref pointing to a subclass object?

I have the following codes:

1. public class Tester
2. {
3.      public static void main(String[] args)
4.      {
5.          A a = new B();
6.          System.out.println(a.getClass());    //Prints class B       
7.          System.out.println(a instanceof A);  //Prints true
8.          System.out.println(a instanceof B);  //Prints true
9.          System.out.println(a.valA);          //Prints 1
10.         System.out.println(a.valB);          //Compilation error
11.
12.     }
13. }
14.
15. class A
16. {
17.     int valA=1;
18. }
19.
20. class B extends A
21. {
22.     int valB=2;
23. }

At line 6 it shows that a is of type class B. However when it reaches line 10, the compiler produces an error: location: variable a of type A.

So my question is: What exactly is the class type of a now? Why getClass() shows that it is of type class B, yet the compiler complains it as type A during compilation?

Further more, since a instanceof B is true, why can't I access valB?


To make things clearer:

EDIT: I ran this statement: System.out.println(a); and the output was B@36d98810 which somehow proves that the toString() method of class B was executed. Since variable a can access the toString() method within class B, why can't it access valB which also resides in class B?

Jon Skeet
people
quotationmark

a is not an object. It's a variable.

The type of the variable is A. The type of the object that the value of the variable refers to at execution time is B.

The compiler resolves everything against the compile-time type of the expressions involved - the variable in this case. When trying to resolve the name valB within the compile-time type of A, it fails to find anything - hence the error.

people

See more on this question at Stackoverflow