Para saber essas regrinhas, é só pensar um pouco. Imagine um código escrito assim:
[code]Animal a = new Dog();
try {
a.eat();
} catch(Exception e) {}
[/code]
Se Dog não implementar o throws, esse código dará algum problema? Não. O try catch não pegará nenhuma exception nunca para dog, mas poderá pegar para outros filhos, como Cat ou Mouse.
Agora, imagine que a situação que o renamed colocou.
Onde Animal não lança uma exception, mas dog lança uma exception verificada. Seria possível escrever isso:
Animal a = new Dog();
a.eat();
Mas se a é um dog, existe uma exception verificada! O java não pode exigir um try… catch, pois usuários da classe animal não esperam a exception. Entretanto, quem sobrescreveu dog, disse que ela existe! Percebeu a inconsistência. Lembre-se que você é obrigado a capturar exceptions verificadas!
O problema das exceptions verificadas é exatamente esse. Elas fazem parte da interface pública do método. Você pode reduzir declarações na classe filha, mas não pode incluir mais declarações que o pai tem. Por fazer parte das interface pública, também significa que você não poderá remover uma exception, sem que tenha que recompilar todo código.
Por exemplo, suponha que você decida que o método eat() não deva lançar Exception nenhuma. E então, remove o throws da declaração de Animal. O que acontece? Todo o seu código acusará erro naquele try…catch (no caso de um catch em Exception talvez não, mas se fosse uma CouldNotEatException, certamente daria). O contrário também é válido. Se você adicionar uma exception verificada num método que não tem, o java exigirá a captura ou o rethrow da exception, em todo local que o código for usado.
Por isso, pense com cuidado nas exceptions.