I'll give you an example first (but at the very end is the answer why the controversy).
Let's suposse you are editing a document in a Java-based document editor and after you are done you choose File->Save as... and you chose to save the document into a volume you don't have write permission on. The Editor wouldn't crash on you with an ugly stacktrace, it would simply tell you that it couldn't save the file and it would let you continue editing and/or save to another location.
In such a case it's probably a checked exception was expected, caught and acted upon to graciously recover from it.
On the other hand suposse these a division by zero or a null pointer exception caused by a programming error that rears its ugly head only in certain conditions. That could happen anywhere in the code, the RAM can be corrupted, etc. No API doc would tell you "this method would throw a division by zero if RAM is corrupted".
Checked exceptions should be part of the design and users of that API should prepare to handle them. Unchecked exceptions could happen almost everywhere and are beyond our control.
The controversy arises from programmers using unchecked exceptions (extending from RuntimeException) when they should be using checked exceptions:
- as a shorcut not to be bothered by the compiler
- to make their signatures look simpler
- because they consider that checked exceptions are a dependency issue (if you throw a new checked exception in an implementing class you should modify the interface's signature) and viceversa.