Причина такого поведения заключается в том, что единственным непроверенным исключением в языке Java является RuntimeException и его подклассы. Все другие исключения и ошибки, в том числе и ваши, поскольку это только подклассы Exception (а не RuntimeException), являются проверенными исключениями.
Причина того, что первый пример кода не был помечен компилятором, хотя он использует класс Exception в качестве оператора catch, вызвана иерархией классов. Поскольку все исключения являются производными от Exception, ваш код специально не обрабатывает Exception, а перехватывает все исключения и приводит их к экземпляру Exception. Таким образом, компилятор не может определить, является ли исключение, которое будет перехвачено во время выполнения, проверенным или непроверенным. Во втором блоке кода исключение, которое перехватывается, не является проверенным исключением, поэтому компилятор может определить, что ваш блок перехвата недоступен.