Going by your example,
Dog extends Animal, thus it IS-A specific type of animal. So, a dog knows all about an animal/ a dog displays all characteristics of an animal.
However, an Animal does not know anything about a Dog, so typecasting this into a more specific type can never succeed. Think about it, at runtime an Animal (which could even be human) might be asked to perform a Dog specific work (like barking), which will clearly be illegal.
Only a polymorphic object (that is Actually a Dog object) will work at runtime too (Because it is actually a dog !

.
Animal animal = new Dog();
Dog d = (Dog) animal; // Compiles and runs.
the opposite of this is upcasting where any Dog object might be casted into Animal class.
Please do note that now even if the object is a Dog, it can only perform Animal specific tasks. Trying to do Dog (or any other subclass specific task will simply not compile)