Vou dar um exemplo primeiro (mas no final está a resposta por que a controvérsia).
Vamos supor que você esteja editando um documento em um editor de documentos baseado em Java e, após concluir, escolha Arquivo-> Salvar como ... e você escolheu salvar o documento em um volume no qual não tenha permissão de gravação. O Editor não trava em você com um traço de pilha feio, simplesmente informa que não foi possível salvar o arquivo e permite continuar editando e / ou salvando em outro local.
Nesse caso, é provável que uma exceção verificada fosse esperada, capturada e usada para se recuperar graciosamente dela.
Por outro lado, suponha a eles uma divisão por zero ou uma exceção de ponteiro nulo causada por um erro de programação que eleva sua cabeça feia apenas em determinadas condições. Isso pode acontecer em qualquer lugar do código, a RAM pode estar corrompida etc. Nenhum documento da API diria "esse método geraria uma divisão por zero se a RAM estiver corrompida" .
As exceções verificadas devem fazer parte do design e os usuários dessa API devem se preparar para lidar com elas. Exceções não verificadas podem acontecer em quase todos os lugares e estão além do nosso controle.
A controvérsia surge dos programadores que usam exceções não verificadas (estendendo-se do RuntimeException) quando devem usar exceções verificadas:
- como um atalho para não ser incomodado pelo compilador
- para tornar suas assinaturas mais simples
- porque consideram que as exceções verificadas são um problema de dependência (se você lançar uma nova exceção verificada em uma classe de implementação, deve modificar a assinatura da interface) e vice-versa.