A subclasse deve lançar as mesmas exceções checked da classe mãe.
Ela pode também lançar menos exceções.
Mas não pode lançar mais exceções. Isso porque um código como esse deve sempre permanecer válido:
Animal animal = loadAnimal();
animal.eat();
Note que na segunda linha, não capturei exceção. Isso pq a sua classe Animal não lançava nenhuma exceção verificada.
O que aconteceria com esse código se dissessemos que Dog pode lançar uma exceção verificada?
Veja que é incompatível. Animal não lança exceção, portanto o código acima é valido. Mas Dog lançaria? Dog é um animal!
Agora, um código assim estaria válido:
try {
Dog d = getDog();
d.eat();
} catch (Exception e)
{
//loga a exceção e mostra um erro
}
Mesmo que o método getDog() retornasse um Terrier, que não lançasse exceção nenhuma. Mesmo que ele faça um try… catch na exceção, não seria obrigatório que o catch seja usado.