The short answer is "because this is
Java, not C++".
The long answer is that you have to keep track of what type of reference you are using at any given time.
Consider the line "c1.m1(c4)".
c4 is a C reference.
c1 is an A reference.
A objs have method m1 that takes an A argument
c4 gets converted into an A reference
the c1 method gets invoked
This isn't like C++ where you invoke according to the most resolved type, one of those subtle language differences. If class A had an overloaded method that also took a C reference as an arg, then you'd get the behaviour you expected. Resolution is done in terms of information available at compile-time, and so the definition of A (the reference type) determines what gets invoked.
Much the same argument for the other two statements.