В С++ спецификация исключения не входит в информацию о типе функции. Единственная проверка, осуществляемая во время компиляции, относится к согласованному использованию исключений: к примеру, если функция или метод возбуждает исключения, то перегруженная или переопределенная версия должна возбуждать те же самые исключения. Однако, в отличие от Java, компилятор не проверяет, действительно ли функция или метод возбуждают данное исключение, или полноту спецификации (то есть описывает ли она все исключения, возможные для этого метода). Если возбуждается исключение, не входящее в спецификацию, программа на С++ вызывает функцию unexpected() из стандартной библиотеки.
Интересно отметить, что из-за использования шаблонов (templates) спецификации исключений отсутствуют в стандартной библиотеке С++. В Java существуют ограничения на использование параметризованных типов со спецификациями исключений.
Перспективы
Во-первых, язык Java, по сути, стал первопроходцем в использовании контролируемых исключений (несомненно из-за спецификаций исключений С++ и того факта, что программисты на С++ не уделяли им слишком много внимания). Это был эксперимент, повторить который с тех пор пока не решился еще ни один язык.
Во-вторых, контролируемые исключения однозначно хороши при рассмотрении вводных примеров и в небольших программах. Оказывается, что трудноуловимые проблемы начинают проявляться при разрастании программы. Конечно, программы не разрастаются тут же и сразу, но они имеют тенденцию расти незаметно. И когда языки, не предназначенные для больших проектов, используются для небольших, но растущих проектов, мы в некоторый момент с удивлением обнаруживаем, что ситуация изменилась с управляемой на затруднительную в управлении. Именно это, как я полагаю, может произойти, когда проверок типов слишком много, и особенно в отношении контролируемых исключений.
Одним из важных достижений Java стала унификация модели передачи информации об ошибках, так как обо всех ошибках
В прошлом я твердо считал, что для разработки надежных программ необходимы и контролируемые исключения, и строгая статическая проверка типов. Однако опыт, полученный лично и со стороны1, с языками, более динамичными, чем статичными, привел меня к мысли, что на самом деле главные преимущества обусловлены следующими аспектами:
1. Унификация модели сообщения об ошибках посредством исключений (независимо от того, заставляет ли компилятор программиста их обрабатывать).
2. Проверка типов, не привязанная к тому, когда она проводится — на стадии компиляции или во время работы программы.
Вдобавок снижение ограничений времени компиляции весьма положительно отражается на продуктивности программиста. С другой стороны, для компенсации чрезмерной жесткости статической проверки типов необходимы
Некоторые уверяли меня, что все сказанное является кощунством, безнадежно испортит мою репутацию, приведет к гибели цивилизации и провалу большой доли программных проектов. Вера в то, что выявление ошибок на стадии компиляции спасет ваш проект, весьма сильна, но гораздо важнее сознавать ограничения того, на что способен компьютер. Стоит помнить:
В любом случае исчезновение когда-либо из Java контролируемых исключений весьма маловероятно. Это слишком радикальное изменение языка, и защитники их в Sun весьма сильны. История Sun неотделима от политики абсолютной обратной совместимости — фактически любое программное обеспечение Sun работает на любом оборудовании Sun, как бы старо оно ни было. Но, если вы чувствуете, что контролируемые исключения становятся для вас препятствием (особенно если вас заставляют обрабатывать исключение, а вы не знаете, как с ним поступить), существует несколько вариантов.
Передача исключений на консоль
В несложных программах, как во многих примерах данной книги, простейшим решением является передача исключения за пределы метода main(), на консоль. К примеру, при открытии файла для чтения (подробности вы вскоре узнаете) необходимо открыть и закрыть поток FilelnputStream, который возбуждает исключения. В небольшой программе можно поступить следующим образом (подобный подход характерен для многих примеров книги):
//• excepti ons/Mai nExcepti on.java
import java io *;