Почему при вызове функции необходимо «выбрасывать исключение»?


98
class throwseg1
{
    void show() throws Exception
    {
        throw new Exception("my.own.Exception");
    }

    void show2() throws Exception  // Why throws is necessary here ?
    {
        show();
    }

    void show3() throws Exception  // Why throws is necessary here ?
    {
        show2();
    }

    public static void main(String s[]) throws Exception  // Why throws is necessary here ?
    {
        throwseg1 o1 = new throwseg1();
        o1.show3();
    }
}

Почему компилятор сообщает , что методы show2(), show3()и main()есть

незарегистрированное исключение Исключение, которое необходимо перехватить или объявить для выброса

когда уберу throws Exceptionиз этих методов?


2
@PaulTomblin main, безусловно, можно объявить, чтобы выбросить исключение. Если это произойдет, JVM выключится. Это настолько близко к игнорированию, насколько позволяет компилятор.
Taymon

Когда вызываемый метод ( Methdod1 ) выбрасывает Exception, мы должны определить вызывающий метод ( Method2 ) с помощью throws Exception; если мы не обрабатываем это исключение в вызывающем методе. Цель этого состоит в том, чтобы предупредить вызывающий метод ( Method3 ) метода Method2, что исключение может быть сгенерировано Method2, и вы должны обработать его здесь, иначе это может прервать вашу программу.
Рито

Точно так же, если Method3 не обрабатывает исключение в своем теле, тогда он должен был определить throws Exceptionв своем определении метода , чтобы указать его вызывающий метод. продолжение предыдущего комментария
Rito

Ответы:


144

В Java, как вы, возможно, знаете, исключения можно разделить на две категории: одно, для которого требуется это throwsпредложение, или которое должно обрабатываться, если вы не укажете одно, и другое, для которого нет. Теперь посмотрите на следующий рисунок:

введите описание изображения здесь

В Java вы можете выбросить все, что расширяет Throwableкласс. Однако вам не нужно указывать throwsпредложение для всех классов. В частности, классы , которые являются либо Errorили RuntimeExceptionили любой из подклассов этих двух. В вашем случае Exceptionэто не подкласс Errorили RuntimeException. Итак, это проверенное исключение, и оно должно быть указано в throwsпредложении, если вы не обрабатываете это конкретное исключение. Вот почему вам понадобилась throwsстатья.


Из учебника по Java :

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

Теперь, как вы знаете, исключения делятся на две группы: отмеченные и непроверенные. Почему эта классификация?

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

Непроверенные исключения: их снова можно разделить на два: ошибки и исключения времени выполнения. Одна из причин, по которой они не должны быть отмечены, заключается в том, что их много, и необходимость обработки всех из них загромождает нашу программу и снижает ее ясность. Другая причина:

  • Исключения во время выполнения: они обычно происходят из-за ошибки программиста. Например, если происходит ArithmeticExceptionделение на ноль или ArrayIndexOutOfBoundsExceptionпроисходит это, это потому, что мы недостаточно осторожны в нашем кодировании. Обычно они случаются из-за каких-то ошибок в логике нашей программы. Таким образом, они должны быть очищены до того, как наша программа перейдет в рабочий режим. Они не отмечены в том смысле, что наша программа должна давать сбой, когда это происходит, чтобы мы, программисты, могли решить эту проблему во время разработки и тестирования.

  • Ошибки: ошибки - это ситуации, из которых обычно программа не может восстановиться. Например, если StackOverflowErrorпроисходит ошибка, наша программа не может многое сделать, например, увеличить размер стека вызовов функций программы. Или, если это OutOfMemoryErrorпроизойдет, мы не сможем значительно увеличить объем оперативной памяти, доступной для нашей программы. В таких случаях лучше выйти из программы. Вот почему они сделаны непроверенными.

Подробную информацию см .:


что я получил из вашего ответа, так это то, что класс Error и его подклассы, а также класс RuntimeException и его подклассы подпадают под непроверенное исключение (например, System.out.println (5/0); нет необходимости бросать, поскольку это исключение времени выполнения, но все же мы можем применить try catch), и класс Exception проверяется, поэтому нам нужно объявить предложение throws в этом методе и каждом методе, который его вызывает
nr5

Еще один вопрос: если исключения разделены на непроверенные и отмеченные, особенно непроверенные (ошибки времени выполнения), чтобы избежать большего количества ошибок во время компиляции?
nr5

@Jomoos - предположим, что код внутри метода выдает исключение IOException. Тогда можно ли в объявлении метода указать "throws Exception"?
MasterJoe 05

ой. Я понял теперь. есть исключение из правил иерархии исключений. Делает. Отлично. Смысл. Спасибо, Java.
JJS

25

Java требует, чтобы вы обрабатывали или объявляли все исключения. Если вы не обрабатываете исключение с помощью блока try / catch, оно должно быть объявлено в сигнатуре метода.

Например:

class throwseg1 {
    void show() throws Exception {
        throw new Exception();
    }
}

Следует записать как:

class throwseg1 {
    void show() {
        try {
            throw new Exception();
        } catch(Exception e) {
            // code to handle the exception
        }
    }
}

Таким образом вы можете избавиться от объявления "throws Exception" в объявлении метода.


7
Все исключения, не являющиеся подклассами RuntimeException.
yshavit

если есть какой-либо другой класс, например Exception, который проверяется?
nr5

1
Что вы имеете в виду? Поскольку все объекты исключений имеют в качестве базового класса «Exception», если вы поймаете объект «Exception» (как в моем примере), он перехватит любое возникшее исключение. Чтобы быть более конкретным (поскольку для разных исключений, вероятно, потребуются разные способы обработки), у вас должно быть несколько блоков catch.
jebar8

если бы я сказал, что проверенные исключения нужно обрабатывать во время компиляции и перехватывать во время выполнения. Я прав ? если да, то такое же предложение для исключения Unchecked будет?
nr5

@ jebar8 - вы путаете Java с .NET - в Java бросаемые объекты должны наследоваться Throwable(наследование Exceptionтакже работает, потому что оно расширяется Throwable, но это не обязательно).
BrainSlugs83

5

throws ExceptionДекларация представляет собой автоматизированный способ отслеживания методов , которые могли бы бросить исключение для ожидаемых , но неизбежных причин. Объявление обычно специфично для типа или типов исключений, которые могут быть выданы, например throws IOExceptionили throws IOException, MyException.

У всех нас есть или мы в конечном итоге напишем код, который неожиданно останавливается и сообщает об исключении из-за чего-то, чего мы не ожидали перед запуском программы, например деления на ноль или индекса за пределами. Поскольку метод не ожидал ошибок, их нельзя было «поймать» и обработать с помощью предложения try catch. Любые ничего не подозревающие пользователи метода также не узнают об этой возможности, и их программы также остановятся.

Когда программист знает, что могут возникать определенные типы ошибок, но хотел бы обрабатывать эти исключения вне метода, метод может «выбросить» один или несколько типов исключений в вызывающий метод вместо их обработки. Если программист не объявил, что метод (может) вызвать исключение (или если у Java не было возможности объявить его), компилятор не мог бы знать, и будущий пользователь метода должен был бы знать об этом, ловить и обрабатывать любые исключения, которые может вызвать метод. Поскольку в программах может быть много уровней методов, написанных множеством разных программ, становится трудно (невозможно) отслеживать, какие методы могут вызывать исключения.

Несмотря на то, что в Java есть возможность объявлять исключения, вы все равно можете написать новый метод с необработанными и необъявленными исключениями, и Java скомпилирует его, и вы сможете запустить его в надежде на лучшее. Что Java не позволяет вам сделать, так это скомпилировать ваш новый метод, если он использует метод, который был объявлен как генерирующее исключение (я), если вы не обрабатываете объявленное исключение (я) в своем методе или не объявляете свой метод как генерирующий то же исключение (я) или если есть несколько исключений, вы можете обработать некоторые и выбросить остальные.

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

Хорошая особенность этого типа решения заключается в том, что когда компилятор сообщает, Error: Unhandled exception type java.io.IOExceptionон предоставляет файл и номер строки метода, который был объявлен для создания исключения. Затем вы можете просто отказаться от ответственности и объявить, что ваш метод также «генерирует исключение IOException». Это может быть выполнено вплоть до основного метода, где это приведет к остановке программы и сообщению об исключении пользователю. Однако лучше перехватить исключение и обработать его удобным способом, например, объяснить пользователю, что произошло и как это исправить. Когда метод перехватывает и обрабатывает исключение, ему больше не нужно объявлять исключение. На этом доллар останавливается, так сказать.


4

Exception- проверенный класс исключения. Следовательно, любой код, вызывающий метод, объявляющий, что он throws Exceptionдолжен его обработать или объявить.


Каждый метод в цепочке объявляется генерирующим исключение, включая main. Так в чем проблема?
Paul Tomblin

@PaulTomblin, я спрашиваю, почему необходимо писать исключение throws в вызывающих функциях, вызывая функцию, которая генерирует исключение
nr5

Хорошо, я не понял, почему вы спрашивали об ошибке компилятора, которую вы на самом деле не получили из опубликованного кода. Это странный способ спросить.
Paul Tomblin

0
package javaexception;


public class JavaException {
   void show() throws Exception
    {
        throw new Exception("my.own.Exception");
    }

void show2() throws Exception  // Why throws is necessary here ?
{
    show();
}

void show3() throws Exception  // Why throws is necessary here ?
{
    show2();
}
public static void main(String[] args) {

   JavaException a = new JavaException();

   try{
   a.show3();
   }catch(Exception e){
       System.out.println(e.getMessage());
   }
}

Только небольшие изменения в вашей программе. Кажется, что многие неправильно понимают основную проблему: всякий раз, когда вы генерируете исключение, которое вам нужно обработать, не обязательно в одном и том же месте (например, метод show1,2,3 в вашей программе), но вы должны сначала использовать метод вызывающего внутри «основного». Одним словом, есть «бросок», должен быть «поймать / попытаться», даже если это не тот метод, в котором происходит исключение.


0
void show() throws Exception
{
    throw new Exception("my.own.Exception");
}

Поскольку в методе show () есть проверенное исключение, которое не обрабатывается в этом методе, мы используем ключевое слово throws для распространения исключения.

void show2() throws Exception //Why throws is necessary here ?
{
show();
}

Поскольку вы используете метод show () в методе show2 () и распространили исключение, по крайней мере, вы должны обрабатывать здесь. Если вы здесь не обрабатываете исключение, значит, вы используете ключевое слово throws. Это причина использования ключевого слова throws в сигнатуре метода.


0

Если вы распространяете исключение, объявляя директиву throws в сигнатуре текущего метода, то где-то вверху по строке или стеку вызовов должна использоваться конструкция try / catch для обработки исключения.


Этот комментарий следует добавить в раздел комментариев, поскольку он не дает поддающегося проверке ответа или его примера. - stackoverflow.com/help/how-to-answer
Пол Доусон

-1

В принципе, если вы не обрабатываете исключение в том же месте, где вы его генерируете, тогда вы можете использовать «генерирует исключение» в определении функции.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.