Философия Java


Ограничения исключений - часть 2


// унаследованные исключения:

void atBat() throws PopFoul {} public static void main(String[] args) { try { StormyInning si = new StormyInning(); si.atBat(); } catch(PopFoul e) { System.err.println("Pop foul"); } catch(RainedOut e) { System.err.println("Rained out"); } catch(BaseballException e) { System.err.println("Generic error"); } // Strike не выбрасывается в унаследованной версии.

try { // Что случится при обратном приведении?

Inning i = new StormyInning(); i.atBat(); // Вы должны ловить исключения от метода

// версии базового класса:

} catch(Strike e) { System.err.println("Strike"); } catch(Foul e) { System.err.println("Foul"); } catch(RainedOut e) { System.err.println("Rained out"); } catch(BaseballException e) { System.err.println( "Generic baseball exception"); } } } ///:~

В Inning вы можете увидеть, что и конструктор, и метод event( ) говорят о том, что они будут выбрасывать исключение, но они не делают этого. Это допустимо, потому что это позволяет вам заставить пользователя ловить любое исключение, которое может быть добавлено и перегруженной версии метода event( ). Эта же идея применена к абстрактным методам, как видно в atBat( ).

Интересен interface Storm, потому что он содержит один метод (event( )), который определен в Inning, и один метод, которого там нет. Оба метода выбрасывают новый тип исключения: RainedOut. Когда StormyInning расширяет Inning и реализует Storm, вы увидите, что метод event( ) в Storm не может изменить исключение интерфейса event( ) в Inning. Кроме того, в этом есть здравый смысл, потому что, в противном случае, вы никогда не узнаете, что поймали правильную вещь, работая с базовым классом. Конечно, если метод, описанный как интерфейс, не существует в базовом классе, такой как rainHard( ), то нет проблем, если он выбросит исключения.

Ограничения для исключений не распространяются на конструкторы. Вы можете видеть в StormyInning, что конструктор может выбросить все, что хочет, не зависимо от того, что выбрасывает конструктор базового класса. Но, так как конструктор базового класса всегда, так или иначе, должен вызываться (здесь автоматически вызывается конструктор по умолчанию), конструктор наследованного класса должен объявить все исключения конструктора базового класса в своей спецификации исключений. Заметьте, что конструктор наследованного класса не может ловить исключения, выброшенные конструктором базового класса.




Начало  Назад  Вперед