Здравствуйте, vsb, Вы писали:
vsb>Здравствуйте, jazzer, Вы писали:
J>>Так в С++ как раз совершенно другая картина, именно из-за того, что 1) исключения не летят откуда угодно, потому что нет рантайма, который бы их бросал, и 2) из-за наличия деструкторов, в которые ты кладешь код очистки/отката в случае неудачи — именно за счет деструкторов в С++ достигается автоматическая обработка исключений.
J>>В D тем же самым занимается scope(failure).
J>>А в Java этого нет, да. Нам их тоже жалко
J>>Цитата относится больше к Java, чем не к исключениям вообще.
vsb>В Java есть try-with-resources, он ничем не хуже вышеперечисленных вариантов.
Я, конечно, давно на это смотрел в последний раз, но, насколько я помню, try-with-resources работает только для совсем примитивных случаев.
Т.е. для одного файла он сработает, а вот для массива файлов — уже нет.
Плюс надо явно указывать все, что ты хочешь, чтоб освободилось в случае исключения, никакой автоматики, как в С++, нет.
Плюс там могут быть только декларации, если хочешь в промежутке между декларациями позвать еще какой-то код — придется писать еще один уровень try/catch.
Поправь, если не так.
vsb>Аналог scope(failure) это try-finally. Разница только в том, что в try-finally код освобождения ресурса не находится рядом с объявлением и добавляется один отступ для внутреннего кода. Это менее удобно, но принципиально ничего не меняет.
В Java можно сделать автоматическое Memento (в смысле, чтоб в случае исключения указанная переменная возвращалась к своему предыдущему значению автоматически)?
Ну и в С++ вообще try/catch очень редко появляется в коде.
Именно за счет автоматики деструкторов.
Совершенно нет никакой необходимости использовать try/catch, чтобы написать exception-safe код.
Большинство такого кода вообще try/catch не содержит, а пишется в стиле
Memento m1(a);
// что-то делаем (исключения OK)
File f;
// что-то делаем (исключения OK)
Memento m2(b);
// что-то делаем (исключения OK)
DBConnection db;
// что-то делаем (исключения OK)
// закончили делать
// раз мы пришли сюда, значит, никаих исключений не случилось, коммитим изменения
m1.commit();
m2.commit();
всё. Этот код exception-safe. Где бы ни появилось исключение — a и b корректно откатятся к старым значениям, файлы/сессии закроются, всё автоматически. И никаких try/catch, простой линейный код.
vsb>Разве что деструктор невозможно забыть вызвать, но в принципе в Java есть статические анализаторы кода, которые тебе подскажут, если ты забыл закрыть ресурс. Проблемой при хорошей организации процесса я это не считаю.
Хм. Ну это и про goto можно сказать — что недостаток языка компенсируется правильной организацией процесса и статическими анализаторами кода.