The example shows that in
Java methods can be overridden but member variables can not. It also shows a great case for not allowing direct access to internal variables. If we take your example and create accessors in each class (overridding in Sub) we would get the result: "2,Sub2" instead of the current result: "3,Sub2"!
For the case of S1 member variable index. Java knows that the type is Super from the declaration. Therefore you get the value of index = 3 because that is what super initializes its member variable to.
In the case of S1 method call, Java knows that the S1 is actually a reference to an object of class Sub, therefore it starts at the Sub class and tries to find a matching method. It finds it there so we get the result from Sub class for printVal.
Manfred.