Java: проверено vs непроверенное объяснение исключения
Я прочитал несколько сообщений в StackOverFlow о проверенных и непроверенных исключениях. Честно говоря, я до сих пор не совсем уверен, как правильно их использовать.
Джошуа блох в "Эффективная Java" сказал, что
использовать проверенные исключения для восстанавливаемые условия и среда выполнения исключения для ошибок программирования (Пункт 58 во 2-м издании)
давайте посмотрим, правильно ли я это понимаю.
вот мой понимание проверенного исключения:
try{
String userInput = //read in user input
Long id = Long.parseLong(userInput);
}catch(NumberFormatException e){
id = 0; //recover the situation by setting the id to 0
}
1. Является ли вышеизложенное проверенным исключением?
2. Является ли RuntimeException непроверенным исключением?
вот мое понимание непроверенного исключения:
try{
File file = new File("my/file/path");
FileInputStream fis = new FileInputStream(file);
}catch(FileNotFoundException e){
//3. What should I do here?
//Should I "throw new FileNotFoundException("File not found");"?
//Should I log?
//Or should I System.exit(0);?
}
4. Теперь, не может ли вышеуказанный код также быть проверенным исключением? Я могу попытаться исправить ситуацию? Я Могу? (Примечание: мой 3-й вопрос внутри catch
выше)
try{
String filePath = //read in from user input file path
File file = new File(filePath);
FileInputStream fis = new FileInputStream(file);
}catch(FileNotFoundException e){
//Kindly prompt the user an error message
//Somehow ask the user to re-enter the file path.
}
5. Зачем люди это делают?
public void someMethod throws Exception{
}
почему они позволяют исключению пузыриться? Не лучше ли справиться с ошибкой раньше? Почему пузырь вверх?
EDIT: должен ли я всплывать точное исключение или маскировать его с помощью исключения?
Ниже приведены мои показания
21 ответов
многие говорят, что проверенные исключения (т. е. те, которые вы должны явно поймать или перестроить) не должны использоваться вообще. Например, они были исключены в C#, и большинство языков их не имеют. Таким образом, вы всегда можете бросить подкласс RuntimeException
(исключение непроверенное)
тем не менее, я думаю, что проверенные исключения полезны - они используются, когда вы хотите заставить пользователя вашего API думать, как справиться с исключительной ситуацией (если она восстанавливается). Просто это проверено. исключения чрезмерно используются в платформе Java, что заставляет людей ненавидеть их.
вот мой расширенный взгляд на тему.
Что касается конкретных вопросов:
- это
NumberFormatException
рассмотрим проверенное исключение?
Нет.NumberFormatException
не установлен (=является подклассомRuntimeException
). Почему? Я не знаю. (но должен же быть какой-то метод!--4-->)Is
RuntimeException
непроверенный исключение?
Да, точно.-
что мне здесь делать?
Это зависит от того, где находится этот код и что вы хотите сделать. Если он находится в слое пользовательского интерфейса - поймайте его и покажите предупреждение; если он находится в слое сервиса - не поймайте его вообще - пусть он пузырится. Только не проглоти исключение. Если в большинстве случаев возникает исключение, следует выбрать одно из следующих:- войти и вернуть
- rethrow it (объявите его брошенным методом)
- создать новое исключение, передав в конструктор
теперь, не может ли вышеуказанный код также быть проверенным исключением? Я могу попытаться исправить ситуацию? Я Могу?
Может быть. Но ничто не мешает вам поймать непроверенное исключение, а такжепочему люди добавляют класс
Exception
в throws пункт?
Чаще всего потому, что людям лень задумываться, что ловить и что переосмысливать. МетаниеException
это порочная практика и ее следует избегать.
увы, нет единого правила, позволяющего определить, когда ловить, когда перестраивать, когда использовать проверенные и когда использовать непроверенные исключения. Я согласен, что это вызывает много путаницы и много плохого кода. Общий принцип изложен Блохом (вы процитировали его часть). И общий принцип чтобы перестроить исключение для слоя, где вы можете его обработать.
является ли что-то" проверенным исключением", не имеет никакого отношения к тому, поймаете ли вы его или что вы делаете в блоке catch. Это свойство классов исключений. Все, что является наследником Exception
за исключением на RuntimeException
и его подклассы являются проверенным исключением.
компилятор Java заставляет вас либо перехватывать проверенные исключения, либо объявлять их в сигнатуре метода. Предполагалось повысить безопасность программы, но большинство считает, что не стоит создавать проблем с дизайном.
почему они позволяют пузырю исключения вверх? Isnt обрабатывать ошибку, чем скорее лучше? Почему пузырь вверх?
потому что это все точка исключений. Без этой возможности вам не понадобились бы исключения. Они позволяют вам обрабатывать ошибки на выбранном вами уровне, а не заставлять вас работать с ними в низкоуровневых методах, где они изначально возникают.
является ли вышеизложенное проверенным исключением? Нет Тот факт, что вы обрабатываете исключение, не делает его проверенным исключением, если это исключение RuntimeException.
является ли RuntimeException непроверенным исключением? Да
проверенные исключения являются подклассами java.ленг.Исключение Непроверенными исключениями являются подклассы java.ленг.К RuntimeException
вызовы бросать проверенные исключения, должны быть заключены в блок try{} или обрабатывается на уровне выше в вызывающем методе. В этом случае текущий метод должен объявить, что он создает указанные исключения, чтобы вызывающие абоненты могли принять соответствующие меры для обработки исключения.
надеюсь, что это помогает.
Q: должен ли я пузыриться точно исключение или маскировать его с помощью исключения?
a: Да, это очень хороший вопрос и важный аспект дизайна. Исключение класса-очень общий класс исключений и может использоваться для обертывания внутренних исключений низкого уровня. Вам лучше создать пользовательское исключение и обернуть его внутри. Но и Большой один - никогда не скрывать в исходной первоначальной причины. Например, Dont ever
сделать следующее -
try {
attemptLogin(userCredentials);
} catch (SQLException sqle) {
throw new LoginFailureException("Cannot login!!"); //<-- Eat away original root cause, thus obscuring underlying problem.
}
вместо этого сделайте следующее:
try {
attemptLogin(userCredentials);
} catch (SQLException sqle) {
throw new LoginFailureException(sqle); //<-- Wrap original exception to pass on root cause upstairs!.
}
съедая исходную первопричину хоронит фактическую причину за пределами восстановления является кошмаром для групп поддержки производства, где все они получают доступ к журналам приложений и сообщения об ошибках.
Хотя последний является лучшим дизайном, но многие люди не используют его часто, потому что разработчики просто не могут передать базовое сообщение вызывающему абоненту. Поэтому сделайте твердую пометку:Always pass on the actual exception
назад, независимо от того, обернуто ли какое-либо исключение конкретного приложения.
на try-catching RuntimeExceptions
RuntimeExceptions как общее правило, не следует пытаться поймать. Они обычно сигнализируют об ошибке программирования и должны быть оставлены в покое. Вместо этого программист должен проверить условие ошибки перед вызовом некоторого кода, который может привести к исключению RuntimeException. Например:
try {
setStatusMessage("Hello Mr. " + userObject.getName() + ", Welome to my site!);
} catch (NullPointerException npe) {
sendError("Sorry, your userObject was null. Please contact customer care.");
}
это плохая практика программирования. Вместо этого нулевая проверка должна была быть выполнена как -
if (userObject != null) {
setStatusMessage("Hello Mr. " + userObject.getName() + ", Welome to my site!);
} else {
sendError("Sorry, your userObject was null. Please contact customer care.");
}
но бывают случаи, когда такая проверка ошибок стоит дорого, например, форматирование чисел, рассмотрим это -
try {
String userAge = (String)request.getParameter("age");
userObject.setAge(Integer.parseInt(strUserAge));
} catch (NumberFormatException npe) {
sendError("Sorry, Age is supposed to be an Integer. Please try again.");
}
здесь предварительная проверка ошибок вызова не стоит усилий, потому что это по существу означает дублировать все код преобразования строки в целое число внутри метода parseInt () - и подвержен ошибкам, если реализован разработчиком. Так что лучше просто покончить с try-catch.
таким образом, NullPointerException и NumberFormatException являются RuntimeExceptions, улавливание NullPointerException должно быть заменено изящной нулевой проверкой, в то время как я рекомендую явно улавливать NumberFormatException, чтобы избежать возможного введения кода, подверженного ошибкам.
1 . Если вы не уверены в исключении, проверьте API:
java.lang.Object extended by java.lang.Throwable extended by java.lang.Exception extended by java.lang.RuntimeException //<-NumberFormatException is a RuntimeException extended by java.lang.IllegalArgumentException extended by java.lang.NumberFormatException
2 . Да, и все исключения, которые его расширяют.
3 . Нет необходимости ловить и выбрасывать одно и то же исключение. В этом случае можно открыть новое диалоговое окно файла.
4 . Исключение filenotfoundexception и уже проверено исключение.
5 . Если ожидается, что метод вызывает someMethod
чтобы поймать исключение, последнее может быть брошено. Он просто "передает мяч". Примером его использования может быть, если вы хотите бросить его в свои собственные частные методы и обработать исключение в своем общедоступном методе.
хорошее чтение само Оракул док: http://download.oracle.com/javase/tutorial/essential/exceptions/runtime.html
почему дизайнеры решили заставить метод указать все необработанные проверенные исключения, которые могут быть брошены в пределах его области? Любое исключение, которое может быть брошенным методом является частью интерфейса открытого программирования метода. Те, кто вызывает метод, должны знать об исключениях, которые метод может вызвать, чтобы они могли решить, что с ними делать. Эти исключения являются такой же частью интерфейса программирования этого метода, как его параметры и возвращаемое значение.
следующий вопрос может быть: "если так хорошо документировать API метода, включая исключения, которые он может бросить, почему бы не указать исключения времени выполнения?" Время выполнения исключения представляют собой проблемы, которые являются результатом проблемы программирования, и как таковой, клиентский код API не может разумно ожидать восстановления из них или обрабатывать их каким-либо образом. Такие проблемы включают арифметические исключения, такие как деление на ноль; исключения указателя, такие как попытка доступа к объекту через нулевую ссылку; и исключения индексирования, такие как попытка доступа к элементу массива через индекс, который слишком велик или слишком мал.
там также важный бит информации в Спецификация Языка Java:
проверенные классы исключений, названные в предложении throws, являются частью контракта между исполнителем и пользователем метода или конструктора.
суть IMHO в том, что вы can поймать любой RuntimeException
, но вы не обязаны и, по сути, реализация не требуется поддерживать то же самое непроверенные исключения, поскольку они не являются частью контракта.
1) Нет, исключение NumberFormatException является непроверенным исключением. Даже если вы поймали его(вы не обязаны), он не установлен. Это потому, что это подкласс IllegalArgumentException который является подклассом RuntimeException.
2) RuntimeException является корнем всех непроверенных исключений. Каждый подкласс RuntimeException не установлен. Все остальные исключения и Throwables проверяются, за исключением ошибок (которые входят в Throwable).
3/4) можно предупредите пользователя, что они выбрали несуществующий файл и попросите новый. Или просто прекратите сообщать пользователю, что они ввели что-то недопустимое.
5) бросать и ловить "исключение" - плохая практика. Но в более общем плане вы можете выбросить другие исключения, чтобы вызывающий абонент мог решить, как с ним справиться. Например, если вы написали библиотеку, чтобы обработать чтение некоторого файла, и ваш метод был передан несуществующий файл, вы понятия не имеете, как это сделать. Звонящий хочет спросить снова или бросить? Так вы бросаете исключение по цепочке обратно.
во многих случаях возникает непроверенное исключение, потому что программист не проверил входные данные (в случае NumberFormatException в вашем первом вопросе). Вот почему его необязательно ловить их, потому что есть более элегантные способы избежать создания этих исключений.
Checked-склонен к этому. Проверено во время компиляции.
например.. FileOperations
UnChecked-из-за плохих данных. Проверено время выполнения.
например..
String s = "abc";
Object o = s;
Integer i = (Integer) o;
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
at Sample.main(Sample.java:9)
здесь исключение связано с плохими данными и никоим образом не может быть определено во время компиляции.
проверенные исключения проверяются во время компиляции JVM и его связанными с ресурсами(files/db/stream/socket etc). Мотив проверяемого исключения заключается в том, что во время компиляции, если ресурсы недоступны, приложение должно определить альтернативное поведение для обработки этого в блоке catch/finally.
непроверенные исключения-это чисто программные ошибки, неправильный расчет, нулевые данные или даже сбои в бизнес-логике могут привести к исключениям во время выполнения. Его абсолютно отлично обрабатывать / ловить непроверенные исключения в коде.
объяснение взято из http://coder2design.com/java-interview-questions/
я просто хочу добавить некоторые рассуждения о том, чтобы вообще не использовать проверенные исключения. Это не полный ответ, но я чувствую, что он отвечает на часть вашего вопроса и дополняет многие другие ответы.
всякий раз, когда проверенные исключения участвуют, есть throws CheckedException
где-то в сигнатуре метода (CheckedException
может быть любым проверенным исключением). Подпись не создает исключение, исключение-это аспект реализации. Интерфейсы, сигнатуры методов, родительские классы, все эти вещи не должны зависеть от их реализации. Использование проверенных исключений здесь (на самом деле тот факт, что вы должны объявить throws
в сигнатуре метода) связывает ваши интерфейсы более высокого уровня с вашими реализациями этих интерфейсов.
позвольте мне показать вам пример.
давайте иметь хороший и чистый интерфейс такой
public interface IFoo {
public void foo();
}
теперь мы можем написать много реализаций метода foo()
, как эти
public class Foo implements IFoo {
@Override
public void foo() {
System.out.println("I don't throw and exception");
}
}
класс Foo в полном порядке. Теперь давайте сделаем первую попытку в class Bar
public class Bar implements IFoo {
@Override
public void foo() {
//I'm using InterruptedExcepton because you probably heard about it somewhere. It's a checked exception. Any checked exception will work the same.
throw new InterruptedException();
}
}
эта панель классов не будет компилироваться. Поскольку InterruptedException является проверенным исключением, вы должны либо захватить его (с помощью метода try-catch inside foo ()), либо объявить, что вы бросаете его (добавление throws InterruptedException
к сигнатуре метода). Поскольку я не хочу фиксировать это исключение здесь (я хочу, чтобы оно распространялось вверх, чтобы я мог правильно справиться с ним где-то еще), Давайте изменим подпись.
public class Bar implements IFoo {
@Override
public void foo() throws InterruptedException {
throw new InterruptedException();
}
}
эта панель классов также не будет компилироваться! Метод foo () бара не переопределяет метод foo() IFoo, поскольку их подписи различны. Я мог бы удалить аннотацию @Override, но я хочу программировать против интерфейса IFoo, как IFoo foo;
и позже решите, какую реализацию я хочу использовать, например foo = new Bar();
. Если метод бара foo () не переопределяет метод IFoo foo, когда я делаю foo.foo();
он не будет вызывать реализацию бара foo().
для сделать бар public void foo() throws InterruptedException
переопределить это IFoo public void foo()
Я должен добавить throws InterruptedException
для подписи метода IFoo. Это, однако, вызовет проблемы с моим классом Foo, так как подпись метода foo() отличается от подписи метода IFoo. Более того, если я добавлю throws InterruptedException
к методу Foo foo() я бы получил еще одну ошибку, заявив, что метод Foo foo () объявляет, что он бросает InterruptedException, но он никогда не бросает InterruptedException.
как вы можете видеть (если бы я сделал достойную работу в объясняя этот материал), тот факт, что я бросаю проверенное исключение, такое как InterruptedException, заставляет меня связать мой интерфейс IFoo с одной из его реализаций, что, в свою очередь, вызывает хаос в других реализациях IFoo!
это одна большая причина, почему проверенные исключения плохие. В кепках.
одно из решений-захватить проверенное исключение, обернуть его в непроверенное исключение и бросить непроверенное исключение.
чтобы ответить на последний вопрос (другие, похоже, полностью ответили выше), "должен ли я пузырить точное исключение или маскировать его с помощью исключения?"
Я предполагаю, что вы имеете в виду что-то вроде этого:
public void myMethod() throws Exception {
// ... something that throws FileNotFoundException ...
}
нет, всегда объявляйте самые точные исключение возможно, или список таких. Исключения, которые вы объявляете способными к выбрасыванию, являются частью контракта между вашим методом и вызывающим объектом. Метание "FileNotFoundException" означает возможно, имя файла недопустимо, и файл не будет найден; вызывающему абоненту нужно будет обработать это разумно. Бросать " исключение "означает" Эй, дерьмо случается. Сделка."Это очень плохой API.
в комментариях к первой статье есть несколько примеров, когда " исключение бросков "является действительным и разумным объявлением, но это не относится к большинству" нормальных " кодов, которые вы когда-либо напишете.
- Java различают две категории исключений (checked & unchecked)
- Java применяет catch или объявленное требование для проверенных исключений
- тип исключения определяет, включено или выключено исключение.
- все исключения типов, прямые или косвенные подклассы классом RuntimeException являются непроверенным исключением.
- все классы, наследующие от исключения класса, но не RuntimeException считаются проверенными исключениями.
- классы, наследующие от ошибки класса, считаются непроверенными.
- компилятор проверяет каждый вызов метода и замедление, чтобы определить,
метод вызывает проверенное исключение.
- если это так, компилятор гарантирует, что исключение поймано или объявлено в предложении throws.
- чтобы удовлетворить часть объявления требования catch-or - declare, метод, который генерирует исключение должно предоставьте предложение throws, содержащее проверенное исключение.
- классы исключений определяются для проверки, когда они считаются достаточно важными, чтобы поймать или объявить.
почему они позволяют исключению пузыриться? Не лучше ли справиться с ошибкой раньше? Почему пузырь вверх?
например, скажем, у вас есть некоторые клиент-серверное приложение и клиент сделал запрос на какой-то ресурс,который не мог быть выяснен или для чего-то еще ошибка некоторые могли произойти на стороне сервера при обработке запроса пользователя, то это обязанность сервера, чтобы сказать клиенту, почему он не мог получить то, что он просил, так что чтобы достичь этого на стороне сервера, код записывается для создания исключения с помощью бросить ключевое слово вместо глотания или регулировать его.если сервер обрабатывает его / проглатывает его, то не будет никакого шанса намекнуть клиенту, что произошла ошибка.
Примечание:чтобы дать четкое описание того, что типа произошла ошибка, мы можем создать наш собственный объект исключения и бросить его клиенту.
мой абсолютный фаворит описание разницы между непроверенными и проверенными исключениями предоставляется статьей Java Tutorial trail,"непроверенные исключения-полемика" (извините, что все элементарно на этом посту-но, эй, основы иногда лучшие):
вот основное правило: если клиент может быть разумно ожидается восстановление из исключения, сделайте его проверенным исключением. Если клиент не может сделать что-нибудь, чтобы оправиться от исключения, сделать это исключение непроверенное
сердце "какого типа исключения выбрасывать" является семантическим (в некоторой степени), и приведенная выше цитата обеспечивает и отличное руководство (следовательно, я все еще поражен тем, что C# избавился от проверенных исключений - особенно, поскольку Лисков утверждает их полезность).
остальное становится логичным: на какие исключения компилятор ожидает от меня явного ответа? Единица от которого вы ожидаете восстановления клиента.
Исключения Времени Выполнения Исключения среды выполнения называются непроверенными исключениями. Все остальные исключения проверяются исключения, и они не являются производными от java.ленг.Исключение RuntimeException.
Проверенные Исключения Проверенное исключение должно быть поймано где-то в коде. Если вы вызываете метод, который создает проверенное исключение, но вы не ловите проверенное исключение где-то, ваш код не будет компилироваться. Вот почему их называют проверенными. исключения: компилятор проверяет, обработаны ли они или объявлены.
ряд методов в Java API throw проверил исключения, поэтому вы часто будете писать обработчики исключений, чтобы справиться с исключениями, сгенерированными методами, которые вы не писали.
вот простое правило, которое поможет вам решить. Это связано с тем, как интерфейсы используются в Java.
возьмите свой класс и представьте, что для него разработан интерфейс, такой, что интерфейс описывает функциональность класса, но ни одна из базовых реализаций (как должен интерфейс). Представьте, что вы можете реализовать класс другим способом.
посмотрите на методы интерфейса и рассмотрите исключения, которые они могут бросок:
Если исключение может быть вызвано методом, независимо от базовой реализации (другими словами, он описывает только функциональность), то это, вероятно, должно быть проверенным исключением в интерфейсе.
Если исключение вызвано базовой реализацией,оно не должно быть в интерфейсе. Поэтому это должно быть либо непроверенное исключение в вашем классе (поскольку непроверенные исключения не должны отображаться в сигнатуре интерфейса), либо вы должны обернуть его и выдали как проверенное исключение, которое является частью метода интерфейса.
чтобы решить, следует ли обернуть и перестроить, вы должны снова рассмотреть, имеет ли смысл для пользователя интерфейса немедленно обрабатывать условие исключения, или исключение настолько общее, что вы ничего не можете с этим поделать, и оно должно распространяться вверх по стеку. Имеет ли обернутое исключение смысл, когда выражается как функциональность нового интерфейса, который вы определяете, или это просто носитель для мешка возможных условий ошибки, которые также могут произойти с другими методами? Если первый, он все еще может быть проверенным исключением, иначе он должен быть снят.
обычно вы не должны планировать "пузырьковые" исключения (catch и rethrow). Либо исключение должно обрабатываться вызывающим абонентом (в этом случае оно проверяется), либо оно должно доходить до обработчика высокого уровня (в этом случае проще всего, если оно не отмечено).
Я думаю, что проверенные исключения являются хорошим напоминанием для разработчика, который использует внешнюю библиотеку, что все может пойти не так с кодом из библиотеки в исключительных ситуациях.
подробнее о проверенных и непроверенных исключениях здесь http://learnjava.сегодня/2015/11/checked-vs-unchecked-исключения/
просто чтобы указать, что если вы бросаете проверенное исключение в коде, а улов на несколько уровней выше, вам нужно объявить исключение в подписи каждого метода между вами и уловом. Таким образом, инкапсуляция нарушена, потому что все функции в пути throw должны знать о деталях этого исключения.
короче говоря, исключения, которые ваш модуль или модули выше должны обрабатывать во время выполнения, называются Check-exceptions, другие-unchecked-exceptions, которые являются либо RuntimeException
или Error
.
В этом видео он объясняет проверенные и непроверенные исключения в java. https://www.youtube.com/watch?v=ue2pOqLaArw
все они являются проверенными исключениями. Непроверенные исключения являются подклассами RuntimeException. Решение не в том, как с ними обращаться, а в том, должен ли ваш код их выбрасывать. Если вы не хотите, чтобы компилятор сообщал вам, что вы не обрабатывали исключение, вы используете непроверенное исключение (подкласс RuntimeException). Они должны быть сохранены для ситуаций, которые вы не можете восстановить из, как из ошибок памяти и тому подобное.
Если кто-то заботится о еще одном доказательстве нелюбви к проверенным исключениям, см. Первые несколько абзацев популярной библиотеки JSON:
" хотя это проверенное исключение, оно редко восстанавливается. Большинство абонентов должны просто обернуть это исключение в непроверенное исключение и перестроить:"
Так почему же в мире кто-то заставит разработчиков продолжать проверять исключение, если мы должны "просто обернуть его" вместо этого? лол
http://developer.android.com/reference/org/json/JSONException.html
Проверенные Исключения :
исключения, которые проверяются компилятором для плавного выполнения программы во время выполнения, называются проверенное исключение.
Они происходят во время компиляции.
- если они не обрабатываются должным образом, они дадут ошибку времени компиляции (не исключение).
-
проверяются все подклассы класса исключения, кроме RuntimeException Исключение.
Гипотетический Пример - Предположим, вы покидаете свой дом для экзамена, но если вы проверите, взяли ли вы билет в зал Дома(время компиляции), тогда не будет никаких проблем в экзаменационном зале(время выполнения).
Исключение Непроверенное :
исключения, которые не проверяются компилятором, называются непроверенными исключениями.
Это происходит во время выполнения.
Если эти исключения не обрабатываются должным образом, они не дают ошибку времени компиляции. Но программа будет прервана преждевременно во время выполнения.
-
все подклассы RunTimeException и Error являются непроверенными исключениями.
Гипотетический Пример - Предположим, вы находитесь в своем экзаменационном зале, но каким - то образом в вашей школе произошел пожар (означает во время выполнения), где вы ничего не можете сделать время, но меры предосторожности могут быть сделаны до (время компиляции).
все исключения должны быть проверены исключения.
непроверенными исключениями являются неограниченные gotos. И неограниченные goto считаются плохой вещью.
непроверенные исключения нарушают инкапсуляцию. Чтобы обработать их правильно, все функции в дереве вызовов между метателем и ловцом должны быть известны, чтобы избежать ошибок.
исключения-это ошибки в функции, которая их выдает, но не ошибки в функция, которая их обрабатывает. Цель исключений-дать программе второй шанс, отложив решение о том, является ли это ошибкой или нет, в другой контекст. Только в другом контексте может быть принято правильное решение.