the compiler is giving you error because the method f() in class B is private.
At compile time methods are checked in correspondence to the type of the reference with which they are called.
Eg
The above code will give you an error that display is not a member of A. This is because the reference aObj is of type A and it denotes an object of type B. But during compilation compiler will only consider the type of aObj(which is A) and check if the method is available in A class or not. Since the method is not available in class A so it will not allow you to call it. However if you change the code-
public static void main(
String[] args)
{
B bObj = new B();
bObj.display();
}
Now the compiler will allow you to call display as you are calling the method with bObj which is of type B and class B has a method named display.
Your case is also similiar. The method f in class A is private. So the compiler will check if f() method of class A is accessible or not. Since it is private so it cannot be called. Now you might say that the f() method in class C will be called which is public. But this will happen on runtime. During compilation the compiler doesn't know that ref2 actually denotes an object of type C. What it knows is that ref2 is of type A and f() method in A is private.......
fffeeeewwwwww....