Здравствуйте, vsb, Вы писали:
vsb>Это Checked Exceptions в Java.
Для концептуальной законченности им не хватает нескольких вещей:
1. Полного запрета бросать руками RuntimeException
2. Перевода всех RuntimeException в либо в checked либо в error.
3. Синтаксического сахара позволяющего конвертировать необработанные исключения при выбрасывании их вверх по стеку
Что-то типа:
class UserDao {
exception SQLException translate to DaoException;
User getUser(long id) throws DaoException {
//code can cause SQL exception
}
}
vsb>Во-вторых ряд исключений не вылетит вообще никогда. Например Integer.parseInt("1"). Никогда тут не вылетит исключение NumberFormatException. А компилятор попросит обложить try-catch-ем.
Never say "never". Завтра пользователь поставит локаль где все числа римские, а программист поправит parseInt чтобы он использовал локаль и здравствуй исключение. Большинство таких ситуация вызваны кривым дизайном языка, а не фундаментальными проблемами.
vsb>В-третьих ряд исключений могут вылететь в любом месте. В разных языках по-разному. Например NullPointerException теоретически может вылететь на любой строчке, где есть ссылки или вызывается функций. StackOverflowError может вылететь опять же везде, где вызывается любая функция. Что с ними делать?
Запретить null как класс. Вместо него использовать либо Option, либо вообще ничего не использовать. Как в Scala:
[code=scala]
val userOption:Option[User] = userDao.getUser(userId);
for (user <- userOption) {
doSmth(user);
}
[/code]
vsb>теперь примеряем его на FileInputStream, а оказыавется, что close там хочет кидать IOException. Чего нам делать? Либо добавляем в throws IOException, либо перекидыаем как непроверяемое исключение. И имеем опять что имеем.
По уму нужно было объявлять интерфейс как
class CloseException extends Exception {};
interface Closeable {
void close() throws CloseException;
}
Но разработчики спрева не подумали, а потом у них не хватило яиц поломать обратную несовместимость.
vsb>Если добваляем throws IOException, то куча классов этот IOException никогда кидать не будет. StringWriter, например, пишет во внутренний буффер-строку, никакого там IO нет. А вот при закрытии — изволь, обработай IOException, мало ли, вдруг кинется, в сигнатуре написано же.
LSP никто не отменял. Завтра StringWriter заменят на BufferedFileWriter а вызывающий код должен работать как прежде. Единственный способ достичь этого это корректно обработать исключенние даже если сейчас оно не бросается.