The only reason I can think of is because C is apart of the same inheritance tree as B and B implements m
is a reason why the compiler doesn't complain when the downcast is made.
Whereas the reason for not having a run-time error is that the "Run Time Type Identification (RTTI)" or runtime type checking succeeds (It doesn't harm to cast null to C). Even though it looks like you are just performing an ordinary parenthesized cast [b = (C)m], at run time this cast is checked to ensure that it is in fact the type you think it is. If it weren't, you'd have got a ClassCastException. Try using b = (C)a and you will get a runtime error.
So, JVM only checks if the runtime object has the same type or is a subtype of the cast. This act of checking types at runtime is called RTTI.
1) You can cast a reference variable of type Interface to any non-final class even if they are not related. Read this tutorial for more information.
2) You can cast a null value to any type, there is never any ClassCastException in that...