Наследование классов исключений java

Обзор ограничений, накладываемых на исключения, на примере наследования и реализации интерфейса

Приветствую всех изучающих Java!
Как известно исключения в Java, при наследовании подчиняются требованию сужения спецификации, а не ее расширения, в отличие от обычных классов.
В книге Bruce Eckel «Thinking in Java, 4 ed.» приведено описание ограничений, накладываемых при использовании исключений. Пример кода описывает наследование от базового класса и одновременную реализацию интерфейса, причем у обоих имеются методы с одинаковой сингатурой, но разной спецификацией исключений. Попытки реализации методов интерфейса пересекаются с попытками одновременного переопределения методов базового класса, в результате которых делается упор на недопущение расширения спецификации исключений. Упрощенный пример кода, доносящий идею:

class BaseBallException extends Exception<> class Foul extends BaseBallException<> class Strike extends BaseBallException<> abstract class Inning < //-----Methods---- public Inning() throws BaseBallException<>public void event() throws BaseBallException<> public abstract void atBat() throws Strike, Foul; > class StormException extends Exception<> class RainedOut extends StormException<> class PopFoul extends Foul<> interface Storm < public void event() throws RainedOut; >class StormyInning extends Inning implements Storm < //--------Methods----- public StormyInning() throws RainedOut, BaseBallException<>public StormyInning(String str) throws Foul, BaseBallException<> /**ошибка компиляции - реализация метода Storm.event() throws RainedOut пытается изменить спецификацию * исключений метода Inning.event() throws BaseBallException на новое исключение RainedOut*/ //! public void event() throws RainedOut<> /**требуется переопределение метода event() с пустой спецификацией исключений - это безболезненно в * силу сужения спецификации и необходимо для реализации интерфейса. * В данном случае - единственный вариант*/ public void event() <> public void atBat() throws PopFoul <> > 

Пример можно дополнить другими вариантами спецификаций исключений, перебрав некоторые интересные сочетания:

class BaseBallException extends Exception<> class Foul extends BaseBallException<> class Strike extends BaseBallException<> class LightStrike extends Strike<> class TwistedLightStrike extends LightStrike<> abstract class Inning < //-----Methods---- public Inning() throws BaseBallException<>public void event() throws BaseBallException<> public void event1() throws BaseBallException<> public void event2() <> public void event3() throws RainedOut<> public void event4() throws Strike<> public void event5() throws LightStrike<> > class StormException extends Exception<> class RainedOut extends StormException<> class Drizzle extends RainedOut<> class PopFoul extends Foul<> interface Storm < public void event() throws RainedOut; public void event1(); public void event2() throws RainedOut; public void event3() throws RainedOut; public void event4() throws LightStrike; public void event5() throws Strike; >class StormyInning extends Inning implements Storm < //--------Methods----- public StormyInning() throws RainedOut, BaseBallException<>public StormyInning(String str) throws Foul, BaseBallException<> /**ошибка компиляции - реализация метода Storm.event() throws RainedOut пытается изменить спецификацию * исключений метода Inning.event() throws BaseBallException на новое исключение RainedOut*/ //! public void event() throws RainedOut<> /**ошибка компиляции - реализация метода Storm.event() throws RainedOut c заменой исключния RainedOut на * BaseBallException является попыткой изменить спецификацию исключений этого метода*/ //! public void event() throws BaseBallException<> /**ошибка компиляции - смешаный вариант не проходит по причине обоюдных попыток расширить * спецификацию исключений*/ //! public void event() throws RainedOut, BaseBallException<> /**Единственный и необходимый вариант*/ public void event() <> /**ошибка компиляции - метод интерфейса Storm.event1() не допускает расширения спецификации*/ //! public void event1() throws BaseBallException <> /**Единственный и необходимый вариант - интерфейс требует реализации метода Storm.event1() и * только с чистой спецификацией*/ public void event1()<> /**ошибка компиляции - метод абстрактного базового класса Inning.event() сопротивляется расширению * спецификации*/ //! public void event2() throws RainedOut<> /**Единственный однако не необходимый вариант реализации интерфейсного метода. * Реализация может отсутствовать вовсе т.к. абстрактный базовый класс реализует интерфейсный метод * Storm.event2() throws RainedOut с сужением спецификации исключений*/ //public void event2()<> /**Реализация метода Storm.event3() throws RainedOut может отсутствовать вовсе - абстрактный базовый * класс реализует интерфейсный метод Storm.event3() throws RainedOut, спецификации исключений * совпадают. Но можно и реализовать метод с исходной спецификацией исключений*/ //public void event3() throws RainedOut<> /**также можно в соответствии с иерархией исключений реализовывать методы с последовательным * сужением спецификации исключений вплоть до чистой*/ //public void event3() throws Drizzle<> //public void event3() <> /**Теперь ловим плечо, на котором может быть реализован метод event4()*/ /**Реализация метода event4() требуется т.к. абстрактный базовый класс расширяет, а не сужает * спецификацию исключений*/ /**ошибка компиляции - попытка расширить спецификацию исключений метода интерфейса Storm.event4()*/ //! public void event4() throws Strike<> /**Работает - спецификация метода абстрактного класса сузилась, интерфейса - соответствует*/ //public void event4() throws LightStrike<> /**Работает - здесь и далее обе спецификации исключений сузились*/ //public void event4() throws TwistedLightStrike<> public void event4() <> /**Идея как и для event4(), но на этот раз реализации не требуется - абстрактный класс сужает спецификацию * и реализует интерфейсный метод*/ //! public void event5() throws Strike<> //public void event5() throws LightStrike<> //public void event5() throws TwistedLightStrike<> //public void event5() > 

Очевидно, приведенные выше ограничения и фичи будет не лишним учитывать при проектировании иерархии классов для очередного проекта.

Читайте также:  What apps java based

Источник

Исключения при наследовании

Существует два правила для контролируемых исключений при наследовании:

  • Переопределяемый метод в подклассе не может выбрасывать контролируемые исключения, которые выше по иерархии чем исключения в методе супер класса.
  • Конструктор подкласса должен включить в свой блок throws все классы исключений или их супер классы из блока throws конструктора супер класса, к которому он обращается при создании объекта.

Пример 1. Исключения при наследовании

import java.io.IOException; public class SuperClass < public SuperClass() throws IOException < >public void start() throws IOException < >>
import java.io.FileNotFoundException; import java.io.IOException; public class SubClass extends SuperClass < public SubClass() throws IOException, ArithmeticException < >public void start() throws FileNotFoundException < >>

Если в конструкторе будет выброшено исключение, объект создан не будет.

Пример 2. Исключение в конструкторе

public class ConstructorException < private int i; public ConstructorException(int i) < this.i = 20 / i; >public int getI() < return i; >>
public class ExceptionInConstructorTest < public static void main(String[] args) < ConstructorException p = null; try < p = new ConstructorException(0); >catch (ArithmeticException e) < System.out.println("Гасим исключение конструктора."); >System.out.println(p.getI()); > >

Источник

Русские Блоги

1 Как видно из рисунка, Java делит все ненормальные ситуации на два типа: Исключение и Ошибка, оба из которых наследуют родительский класс Throwable.

2 Ошибки, связанные с ошибками, обычно относятся к проблемам, связанным с виртуальными машинами, таким как сбои системы, ошибки виртуальной машины, сбои динамического соединения и т. Д. Такие ошибки не могут быть восстановлены или их невозможно отследить, что приведет к прерыванию приложения, и обычно приложение не может обработать эти ошибки Поэтому приложения не должны использовать блоки catch для перехвата объектов Error. При определении этого метода нет необходимости объявлять, что метод может выдавать Error и любые подклассы в его предложении throws.

Два примера захвата исключения 1

1 пример кода

public class DivTest < public static void main(String[] args) < try < int a = Integer.parseInt(args[0]); int b = Integer.parseInt(args[1]); int c = a / b; System.out.println («Результат разделения двух введенных вами чисел:» + c); >catch (IndexOutOfBoundsException ie) < System.out.println («массив вне границ: количество параметров, введенных при запуске программы, недостаточно»); >catch (NumberFormatException ne) < System.out.println («Исключение формата чисел: программа может принимать только целочисленные параметры»); >catch (ArithmeticException ae) < System.out.println («Арифметическое исключение»); >catch (Exception e) < System.out.println («Неизвестное исключение»); >> >

2 Результат операции

E:\test\Java\Java8\ExceptionTEST\src>java 8 1
Ошибка: не удается найти или загрузить основной класс 8

E:\test\Java\Java8\ExceptionTEST\src>java DivTest 8 1
Результат деления двух введенных вами чисел: 8

E:\test\Java\Java8\ExceptionTEST\src>java DivTest 8 1 3
Результат деления двух введенных вами чисел: 8

E:\test\Java\Java8\ExceptionTEST\src>java DivTest 8
Массив вне границ: количество параметров, введенных при запуске программы, недостаточно

E:\test\Java\Java8\ExceptionTEST\src>java DivTest 8 d
Ненормальный формат чисел: программа может принимать только целочисленные параметры

E:\test\Java\Java8\ExceptionTEST\src>java DivTest 8 0
Арифметическая аномалия

3 Анализ результатов

Вышеприведенная программа предоставляет специальную логику обработки исключений для 3 типов исключений.

Три NullPointerException

1 пример кода

import java.util.*; public class NullTest < public static void main(String[] args) < Date d = null; try < System.out.println(d.after(new Date())); >catch (NullPointerException ne) < System.out.println («Исключение нулевого указателя»); >catch(Exception e) < System.out.println («Неизвестное исключение»); >> >

2 Результат операции

Исключение нулевого указателя

3 Анализ результатов

Вышеупомянутая программа предоставляет специальный блок обработки исключений для NullPointerException. Вышеприведенная программа вызывает метод after нулевого объекта, который вызывает исключение NullPointerException, а среда выполнения Java вызывает блок catch, соответствующий NullPointerException, для обработки исключения.

Проблема порядка захвата четырех исключений

1 пример кода

 try < System.out.println(d.after(new Date())); >catch(Exception e) < System.out.println («Неизвестное исключение»); >catch (NullPointerException ne)

2 Анализ результатов

Приведенный выше код не может быть скомпилирован, потому что большое исключение помещается перед небольшим исключением и должно быть помещено позади.

При отлове исключений не забудьте сначала отловить небольшие исключения, а затем отловить большие.

Источник

Оцените статью