In your second case, you're casting an
Animal reference to a
Dog reference. Now, that
might work, so it will compile OK. But at run-time the JVM will look at the actual type of the object, which is
Animal, and will try and cast that to a
Dog. That's not possible, because an
Animal is-not-a
Dog, so you get a
ClassCastException.
In the first example you're preceding the cast with an
instanceof check. Which means that for those cases where you would get a
ClassCastException (the first and last elements in the array), it doesn't try and cast. It only tries it for the case where the cast is safe - when the object actually is a
Dog.
You should always check
instanceof before casting an object like that unless you know you can guarantee (from your understanding of the rest of the code) that it is safe.