Ошибка во время исполнения java

Error is an illegal operation performed by the user which results in the abnormal working of the program. Programming errors often remain undetected until the program is compiled or executed. Some of the errors inhibit the program from getting compiled or executed. Thus errors should be removed before compiling and executing. 

The most common errors can be broadly classified as follows:

1. Run Time Error: 

Run Time errors occur or we can say, are detected during the execution of the program. Sometimes these are discovered when the user enters an invalid data or data which is not relevant. Runtime errors occur when a program does not contain any syntax errors but asks the computer to do something that the computer is unable to reliably do. During compilation, the compiler has no technique to detect these kinds of errors. It is the JVM (Java Virtual Machine) that detects it while the program is running. To handle the error during the run time we can put our error code inside the try block and catch the error inside the catch block. 

For example: if the user inputs a data of string format when the computer is expecting an integer, there will be a runtime error. Example 1: Runtime Error caused by dividing by zero 

Java

class DivByZero {

    public static void main(String args[])

    {

        int var1 = 15;

        int var2 = 5;

        int var3 = 0;

        int ans1 = var1 / var2;

        int ans2 = var1 / var3;

        System.out.println(

            "Division of va1"

            + " by var2 is: "

            + ans1);

        System.out.println(

            "Division of va1"

            + " by var3 is: "

            + ans2);

    }

}

Runtime Error in java code:

Exception in thread "main" java.lang.ArithmeticException: / by zero
    at DivByZero.main(File.java:14)

Example 2: Runtime Error caused by Assigning/Retrieving Value from an array using an index which is greater than the size of the array 

Java

class RTErrorDemo {

    public static void main(String args[])

    {

        int arr[] = new int[5];

        arr[9] = 250;

        System.out.println("Value assigned! ");

    }

}

RunTime Error in java code:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 9
    at RTErrorDemo.main(File.java:10)

2. Compile Time Error: 

Compile Time Errors are those errors which prevent the code from running because of an incorrect syntax such as a missing semicolon at the end of a statement or a missing bracket, class not found, etc. These errors are detected by the java compiler and an error message is displayed on the screen while compiling. Compile Time Errors are sometimes also referred to as Syntax errors. These kind of errors are easy to spot and rectify because the java compiler finds them for you. The compiler will tell you which piece of code in the program got in trouble and its best guess as to what you did wrong. Usually, the compiler indicates the exact line where the error is, or sometimes the line just before it, however, if the problem is with incorrectly nested braces, the actual error may be at the beginning of the block. In effect, syntax errors represent grammatical errors in the use of the programming language. 

Example 1: Misspelled variable name or method names 

Java

class MisspelledVar {

    public static void main(String args[])

    {

        int a = 40, b = 60;

        int Sum = a + b;

        System.out.println(

            "Sum of variables is "

            + sum);

    }

}

Compilation Error in java code:

prog.java:14: error: cannot find symbol
            + sum);
              ^
  symbol:   variable sum
  location: class MisspelledVar
1 error

Example 2: Missing semicolons 

Java

class PrintingSentence {

    public static void main(String args[])

    {

        String s = "GeeksforGeeks";

        System.out.println("Welcome to " + s)

    }

}

Compilation Error in java code:

prog.java:8: error: ';' expected
        System.out.println("Welcome to " + s)
                                             ^
1 error

Example: Missing parenthesis, square brackets, or curly braces 

Java

class MissingParenthesis {

    public static void main(String args[])

    {

        System.out.println("Printing 1 to 5 n");

        int i;

        for (i = 1; i <= 5; i++ {

            System.out.println(i + "n");

        }

    }

}

Compilation Error in java code:

prog.java:10: error: ')' expected
        for (i = 1; i <= 5; i++ {
                               ^
1 error

Example: Incorrect format of selection statements or loops 

Java

class IncorrectLoop {

    public static void main(String args[])

    {

        System.out.println("Multiplication Table of 7");

        int a = 7, ans;

        int i;

        for (i = 1, i <= 10; i++) {

            ans = a * i;

            System.out.println(ans + "n");

        }

    }

}

Compilation Error in java code:

prog.java:12: error: not a statement
        for (i = 1, i <= 10; i++) {
                      ^
prog.java:12: error: ';' expected
        for (i = 1, i <= 10; i++) {
                                ^
2 errors

Logical Error: A logic error is when your program compiles and executes, but does the wrong thing or returns an incorrect result or no output when it should be returning an output. These errors are detected neither by the compiler nor by JVM. The Java system has no idea what your program is supposed to do, so it provides no additional information to help you find the error. Logical errors are also called Semantic Errors. These errors are caused due to an incorrect idea or concept used by a programmer while coding. Syntax errors are grammatical errors whereas, logical errors are errors arising out of an incorrect meaning. For example, if a programmer accidentally adds two variables when he or she meant to divide them, the program will give no error and will execute successfully but with an incorrect result. 

Example: Accidentally using an incorrect operator on the variables to perform an operation (Using ‘/’ operator to get the modulus instead using ‘%’) 

Java

public class LErrorDemo {

    public static void main(String[] args)

    {

        int num = 789;

        int reversednum = 0;

        int remainder;

        while (num != 0) {

            remainder = num / 10;

            reversednum

                = reversednum * 10

                  + remainder;

            num /= 10;

        }

        System.out.println("Reversed number is "

                           + reversednum);

    }

}

Output:

Reversed number is 7870

Example: Displaying the wrong message 

Java

class IncorrectMessage {

    public static void main(String args[])

    {

        int a = 2, b = 8, c = 6;

        System.out.println(

            "Finding the largest number n");

        if (a > b && a > c)

            System.out.println(

                a + " is the largest Number");

        else if (b > a && b > c)

            System.out.println(

                b + " is the smallest Number");

        else

            System.out.println(

                c + " is the largest Number");

    }

}

Output:

Finding the largest number 

8 is the smallest Number

Syntax Error:

Syntax and Logical errors are faced by Programmers.

Spelling or grammatical mistakes are syntax errors, for example, using an uninitialized variable, using an undefined variable, etc., missing a semicolon, etc.

int x, y;
x = 10 // missing semicolon (;)
z = x + y; // z is undefined, y in uninitialized.

Syntax errors can be removed with the help of the compiler.

Last Updated :
08 Jun, 2022

Like Article

Save Article

Чтобы разобраться, в чем разница между ошибками времени компиляции и ошибками времени выполнения в Java, разберемся в сути каждого вида.

Ошибки времени компиляции

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

Пример

public class Test{
   public static void main(String args[]){
      System.out.println("Hello")
   }
}

Итог

C:Sample>Javac Test.java
Test.java:3: error: ';' expected
   System.out.println("Hello")

Ошибки времени выполнения

Исключение (или исключительное событие) – это проблема, возникающая во время выполнения программы. Когда возникает исключение, нормальный поток программы прерывается, и программа / приложение прерывается ненормально, что не рекомендуется, поэтому эти исключения должны быть обработаны.

Пример

import java.io.File;
import java.io.FileReader;

public class FilenotFound_Demo {
   public static void main(String args[]) {
      File file = new File("E://file.txt");
      FileReader fr = new FileReader(file);
   }
}

Итог

C:>javac FilenotFound_Demo.java
FilenotFound_Demo.java:8: error: unreported exception
FileNotFoundException; must be caught or declared to be thrown
   FileReader fr = new FileReader(file);
                   ^
1 error

A runtime error in Java is an application error that occurs during the execution of a program. A runtime error occurs when a program is syntactically correct but contains an issue that is only detected during program execution. These issues cannot be caught at compile-time by the Java compiler and are only detected by the Java Virtual Machine (JVM) when the application is running.

Runtime errors are a category of exception that contains several more specific error types. Some of the most common types of runtime errors are:

  • IO errors
  • Division by zero errors
  • Out of range errors
  • Undefined object errors

Runtime Errors vs Compile-Time Errors

Compile-time errors occur when there are syntactical issues present in application code, for example, missing semicolons or parentheses, misspelled keywords or usage of undeclared variables.

These syntax errors are detected by the Java compiler at compile-time and an error message is displayed on the screen. The compiler prevents the code from being executed until the error is fixed. Therefore, these errors must be addressed by debugging before the program can be successfully run.

On the other hand, runtime errors occur during program execution (the interpretation phase), after compilation has taken place. Any code that throws a runtime error is therefore syntactically correct.

Runtime Errors vs Logical Errors

A runtime error could potentially be a legitimate issue in code, for example, incorrectly formatted input data or lack of resources (e.g. insufficient memory or disk space). When a runtime error occurs in Java, the compiler specifies the lines of code where the error is encountered. This information can be used to trace back where the problem originated.

On the other hand, a logical error is always the symptom of a bug in application code leading to incorrect output e.g. subtracting two variables instead of adding them. In case of a logical error, the program operates incorrectly but does not terminate abnormally. Each statement may need to be checked to identify a logical error, which makes it generally harder to debug than a runtime error.

What Causes Runtime Errors in Java

The most common causes of runtime errors in Java are:

  • Dividing a number by zero.
  • Accessing an element in an array that is out of range.
  • Attempting to store an incompatible type value to a collection.
  • Passing an invalid argument to a method.
  • Attempting to convert an invalid string to a number.
  • Insufficient space in memory for thread data.

When any such errors are encountered, the Java compiler generates an error message and terminates the program abnormally. Runtime errors don’t need to be explicitly caught and handled in code. However, it may be useful to catch them and continue program execution.

To handle a runtime error, the code can be placed within a try-catch block and the error can be caught inside the catch block.

Runtime Error Examples

Division by zero error

Here is an example of a java.lang.ArithmeticException, a type of runtime exception, thrown due to division by zero:

public class ArithmeticExceptionExample {
public static void main(String[] args) {
          int a = 10, b = 0;
          System.out.println("Result: "+ a/b);
    }
}

In this example, an integer a is attempted to be divided by another integer b, whose value is zero, leading to a java.lang.ArithmeticException:

Exception in thread "main" java.lang.ArithmeticException: / by zero
        at ArithmeticExceptionExample.main(ArithmeticExceptionExample.java:4)

Accessing an out of range value in an array

Here is an example of a java.lang.ArrayIndexOutOfBoundsExceptionthrown due to an attempt to access an element in an array that is out of bounds:

public class ValueOutOfRangeErrorExample {
    public static void main(String[] args) {
        int arr[] = new int[5];
        System.out.println("5th element in array: " + arr[5]);
    }
}

In this example, an array is initialized with 5 elements. An element at position 5 is later attempted to be accessed in the array, which does not exist, leading to a java.lang.ArrayIndexOutOfBoundsException runtime error:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5
    at ValueOutOfRangeErrorExample.main(ValueOutOfRangeErrorExample.java:4)

How to Solve Runtime Errors

Runtime errors can be handled in Java using try-catch blocks with the following steps:

  • Surround the statements that can throw a runtime error in try-catch blocks.
  • Catch the error.
  • Depending on the requirements of the application, take necessary action. For example, log the exception with an appropriate message.

To illustrate this, the code in the earlier ArithmeticException example can be updated with the above steps:

public class ArithmeticExceptionExample {
    public static void main(String[] args) {
        try {
            int a = 10, b = 0;
            System.out.println("Result: " + a/b);
        } catch (ArithmeticException ae) {
            System.out.println("Arithmetic Exception: cannot divide by 0");
        }
        System.out.println("Continuing execution...");
    }
}

Surrounding the code in try-catch blocks like the above allows the program to continue execution after the exception is encountered:

Arithmetic Exception: cannot divide by 0
Continuing execution…

Runtime errors can be avoided where possible by paying attention to detail and making sure all statements in code are mathematically and logically correct.

Track, Analyze and Manage Errors With Rollbar

![Rollbar in action](https://rollbar.com/wp-content/uploads/2022/04/section-1-real-time-errors@2x-1-300×202.png)

Managing errors and exceptions in your code is challenging. It can make deploying production code an unnerving experience. Being able to track, analyze, and manage errors in real-time can help you to proceed with more confidence. Rollbar automates error monitoring and triaging, making fixing errors easier than ever. Try it today.

Вместо того, чтобы объявить, что int a;вы ошибочно заявили, in a;что компилятор выдаст ошибку.

Пример: вы объявили переменную int a;и после нескольких строк кода вы снова объявляете целое число как int a;. Все эти ошибки подсвечиваются при компиляции кода.

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

Примером исключений являются: арифметическое исключение, исключение нулевого указателя, деление на ноль исключения и т. Д.

Исключения в Java находятся вне контроля разработчиков.

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

Как обрабатывать исключения

До сих пор мы видели, что исключение находится вне контроля разработчика. Но обвинять ваш код ошибки в экологических проблемах не является решением. Вам нужно надежное программирование, которое заботится об исключительных ситуациях. Такой код известен как Exception Handler.

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

Обработка исключений Java

Для этого введите свой код для подключения к серверу (используя традиционные условия if и else).

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

Такая организация кода с использованием циклов «if» и «else» неэффективна, когда ваш код имеет несколько исключений Java для обработки.

class connect{
	if(Server Up){
	 // code to connect to server
	}
	else{
	 // code to connect to BACKUP server
	}
}

Попробуйте Catch Block

Java обеспечивает встроенную исключительную обработку.

  1. Нормальный код входит в блок TRY .
  2. Код обработки исключений входит в блок CATCH


Обработка исключений Java

В нашем примере блок TRY будет содержать код для подключения к серверу. Блок CATCH будет содержать код для подключения к серверу резервного копирования.

Если сервер работает, код в блоке CATCH будет игнорироваться. Если сервер не работает, возникает исключение, и код в блоке catch будет выполнен.

Обработка исключений Java

Итак, вот как исключение обрабатывается в Java.

Синтаксис использования try & catch

try{
    statement(s)
}
catch (exceptiontype name){
	statement(s)
}

пример

Шаг 1) Скопируйте следующий код в редактор

class JavaException {
   public static void main(String args[]){
      int d = 0;
      int n = 20;
      int fraction = n/d;
     System.out.println("End Of Main");
   }
}

Шаг 2) Сохраните файл и скомпилируйте код. Запустите программу, используя команду JavaException

Шаг 3) Арифметическое исключение – деление на ноль показано, как показано ниже для строки № 5, а строка № 6 никогда не выполняется

Шаг 4) Теперь давайте посмотрим, как try и catch помогут нам справиться с этим исключением. Мы поместим исключение, вызывающее строку кода в блок try , за которым следует блок catch . Скопируйте следующий код в редактор.

class JavaException {
 public static void main(String args[]) {
  int d = 0;
  int n = 20;
  try {
   int fraction = n / d;
   System.out.println("This line will not be Executed");
  } catch (ArithmeticException e) {
   System.out.println("In the catch Block due to Exception = " + e);
  }
  System.out.println("End Of Main");
 }
}

Шаг 5) Сохраните, скомпилируйте и запустите код. Вы получите следующий вывод

Обработка исключений Java

Как вы заметили, исключение обрабатывается, и последняя строка кода также выполняется. Также обратите внимание, что строка № 7 не будет выполнена, поскольку, как только возникает исключение, поток управления переходит к блоку перехвата.

Примечание. Объект AritmeticException «e» содержит информацию о возникшем исключении, которая может быть полезна при выполнении действий по восстановлению.

Java Exception class Hierarchy

После выполнения одного оператора catch другие обходятся, и выполнение продолжается после блока try / catch. Вложенные блоки catch следуют иерархии исключений.

Руководство по иерархии исключений Java

  • Все классы исключений в Java расширяют класс Throwable. Throwable имеет два подкласса: ошибка и исключение
  • Класс Error определяет исключение или проблемы, которые не должны возникать в обычных условиях в нашей программе, например ошибка памяти, ошибка оборудования, ошибка JVM и т. Д.
  • Класс Exception представляет исключения, которые могут быть обработаны нашей программой, и наша программа может быть восстановлена ​​из этого исключения, используя блок try и catch
  • Исключение времени выполнения является подклассом класса исключения. Исключение этого типа представляет исключение, которое происходит во время выполнения и которое не может быть отслежено во время компиляции. Отличный пример того же – деление на ноль или исключение нулевого указателя и т. Д.
  • IO исключение генерируется во время операций ввода и вывода
  • Прерванные исключения в Java генерируются при многопоточности.

Пример: чтобы понять вложение блоков try и catch

Шаг 1) Скопируйте следующий код в редактор.

class JavaException {
 public static void main(String args[]) {
  try {
   int d = 1;
   int n = 20;
   int fraction = n / d;
   int g[] = {
    1
   };
   g[20] = 100;
  }
  /*catch(Exception e){
  	System.out.println("In the catch block due to Exception = "+e);
  }*/
  catch (ArithmeticException e) {
   System.out.println("In the catch block due to Exception = " + e);
  } catch (ArrayIndexOutOfBoundsException e) {
   System.out.println("In the catch block due to Exception = " + e);
  }
  System.out.println("End Of Main");
 }
}

Шаг 2) Сохраните файл и скомпилируйте код. Запустите программу, используя команду JavaException .

Шаг 3) Создается исключение ArrayIndexOutOfBoundsException. Измените значение int d на 0. Сохраните, скомпилируйте и запустите код.

Шаг 4 ) Должно быть сгенерировано исключение ArithmeticException.

Шаг 5) Раскомментируйте строку № 10 со строкой № 12. Сохраните, скомпилируйте и запустите код.

Шаг 6) Ошибка компиляции? Это потому, что Exception является базовым классом ArithmeticException Exception. Любое исключение, которое вызывается ArithmeticException, также может быть обработано классом Exception. Так что блок catch ArithmeticException никогда не получит шанс быть выполненным, что делает его избыточным. Отсюда и ошибка компиляции.

Java, наконец, блок

Блок finally выполняется независимо от возникновения исключения в блоке try. Это необязательно использовать с Ьгой блоком.

 try {
  statement(s)
 } catch (ExceptiontType name) {

  statement(s)

 } finally {

  statement(s)

 }

В случае возникновения исключения в блоке try блок finally выполняется после выполнения блока catch.

пример

Шаг 1) Скопируйте следующий код в редактор.

class JavaException {
   public static void main(String args[]){
    try{
       int d = 0;
       int n =20;
       int fraction = n/d;
    }
  catch(ArithmeticException e){
    System.out.println("In the catch block due to Exception = "+e);
  }
  finally{
	System.out.println("Inside the finally block");
  }
}
}

Шаг 2) Сохраните, скомпилируйте и запустите код.

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

Шаг 4) Измените значение переменной d = 1. Сохраните, скомпилируйте и запустите код и просмотрите результат. Нижняя часть формы

Резюме :

  • Исключением является ошибка времени выполнения , которое прерывает нормальный поток программы execution.Disruption во время выполнения программы, называется , как ошибки или исключения.
  • Ошибки делятся на две категории
    • Ошибки времени компиляции – синтаксические ошибки, семантические ошибки
    • Ошибки во время выполнения – исключение
  • Надежная программа должна обрабатывать все исключения и по- прежнему с нормальным потоком выполнения программы. Java предоставляет встроенный исключительный метод обработки
  • Exception Handler – это набор кода, который обрабатывает исключение . Исключения могут быть обработаны в Java с помощью try & catch.
  • Попробуйте блок : нормальный код идет на этот блок.
  • Блок Catch : если в нормальном коде есть ошибка, он перейдет в этот блок

Исключение (exception) — это ненормальная ситуация (термин «исключение» здесь следует понимать как «исключительная ситуация»), возникающая во время выполнения программного кода. Иными словами, исключение — это ошибка, возникающая во время выполнения программы (в runtime).

Исключение — это способ системы Java (в частности, JVM — виртуальной машины Java) сообщить вашей программе, что в коде произошла ошибка. К примеру, это может быть деление на ноль, попытка обратиться к массиву по несуществующему индексу, очень распространенная ошибка нулевого указателя (NullPointerException) — когда вы обращаетесь к ссылочной переменной, у которой значение равно null и так далее.

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

Обработка исключений (exception handling) — название объектно-ориентированной техники, которая пытается разрешить эти ошибки.

Программа в Java может сгенерировать различные исключения, например:

  • программа может пытаться прочитать файл из диска, но файл не существует;

  • программа может попытаться записать файл на диск, но диск заполнен или не отформатирован;

  • программа может попросить пользователя ввести данные, но пользователь ввел данные неверного типа;

  • программа может попытаться осуществить деление на ноль;

  • программа может попытаться обратиться к массиву по несуществующему индексу.

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

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

В Java все исключения представлены отдельными классами. Все классы исключений являются потомками класса Throwable. Так, если в программе возникнет исключительная ситуация, будет сгенерирован объект класса, соответствующего определенному типу исключения. У класса Throwable имеются два непосредственных подкласса: Exception и Error.

Исключения типа Error относятся к ошибкам, возникающим в виртуальной машине Java, а не в прикладной программе. Контролировать такие исключения невозможно, поэтому реакция на них в приложении, как правило, не предусматривается. В связи с этим исключения данного типа не будут рассматриваться в книге.

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

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


Так как в Java
ВСЁ ЯВЛЯЕТСЯ ОБЪЕКТОМ, то исключение тоже является объектом некоторого класса, который описывает исключительную ситуацию, возникающую в определенной части программного кода.

«Обработка исключений» работает следующим образом:

  • когда возникает исключительная ситуация, JVM генерирует (говорят, что JVM ВЫБРАСЫВАЕТ исключение, для описания этого процесса используется ключевое слово throw) объект исключения и передает его в метод, в котором произошло исключение;

  • вы можете перехватить исключение (используется ключевое слово catch), чтобы его каким-то образом обработать. Для этого, необходимо определить специальный блок кода, который называется обработчиком исключений, этот блок будет выполнен при возникновении исключения, код должен содержать реакцию на исключительную ситуацию;

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

Если вы не предусмотрите обработчик исключений, то исключение будет перехвачено стандартным обработчиком Java. Стандартный обработчик прекратит выполнение программы и выведет сообщение об ошибке.

Рассмотрим пример исключения и реакцию стандартного обработчика Java.

public static void main(String[] args) {

System.out.println(5 / 0);

Мы видим, что стандартный обработчик вывел в консоль сообщение об ошибке. Давайте разберемся с содержимым этого сообщения:

«C:Program FilesJavajdk1.8.0_60binjava»

Exception in thread «main» java.lang.ArithmeticException: / by zero

at ua.opu.Main.main(Main.java:6)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:497)

at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

Process finished with exit code 1

Exception in thread «main» java.lang.ArithmeticException: / by zero

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

at ua.opu.Main.main(Main.java:6)

в каком классе, методе и строке произошло исключение. Используя эту информацию, мы можем найти ту строчку кода, которая привела к исключительной ситуации, и предпринять какие-то действия. Строки

at ua.opu.Main.main(Main.java:6)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:497)

at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

называются «трассировкой стека» (stack tracing). О каком стеке идет речь? Речь идет о стеке вызовов (call stack). Соответственно, эти строки означают последовательность вызванных методов, начиная от метода, в котором произошло исключение, заканчивая самым первым вызванным методом.

Для вызова методов в программе используется инструкция «call». Когда вы вызываете метод в программе, важно сохранить адрес следующей инструкции, чтобы, когда вызванный метод отработал, программа продолжила работу со следующей инструкции. Этот адрес нужно где-то хранить в памяти. Также перед вызовом необходимо сохранить аргументы функции, которые тоже необходимо где-то хранить.

Вся эта информация хранится в специальной структуре – стеке вызовов. Каждая запись в стеке вызовов называется кадром или фреймом (stack frame).

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

Как уже было сказано выше, исключение это объект некоторого класса. В Java существует разветвленная иерархия классов исключений.

В Java, класс исключения служит для описания типа исключения. Например, класс NullPointerException описывает исключение нулевого указателя, а FileNotFoundException означает исключение, когда файл, с которым пытается работать приложение, не найден. Рассмотрим иерархию классов исключений:

На самом верхнем уровне расположен класс Throwable, который является базовым для всех исключений (как мы помним, JVM «выбрасывает» исключение», поэтому класс Throwable означает – то, что может «выбросить» JVM).

От класса Throwable наследуются классы Error и Exception. Среди подклассов Exception отдельно выделен класс RuntimeException, который играет важную роль в иерархии исключений.

В Java существует некоторая неопределенность насчет того – существует ли два или три вида исключений.

Если делить исключения на два вида, то это:

  1. 1.

    контролируемые исключения (checked exceptions) – подклассы класса Exception, кроме подкласса RuntimeException и его производных;

  2. 2.

    неконтролируемые исключения (unchecked exceptions) – класс Error с подклассами, а также класс RuntimeException и его производные;

В некоторых источниках класс Error и его подклассы выделяют в отдельный вид исключений — ошибки (errors).

Далее мы видим класс Error. Классы этой ветки составляют вид исключений, который можно обозначить как «ошибки» (errors). Ошибки представляют собой серьезные проблемы, которые не следует пытаться обработать в собственной программе, поскольку они связаны с проблемами уровня JVM.

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

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

В качестве примеров «ошибок» можно привести: переполнение стека вызова (класс StackOverflowError); нехватка памяти в куче (класс OutOfMemoryError), вследствие чего JVM не может выделить память под новый объект и сборщик мусора не помогает; ошибка виртуальной машины, вследствие которой она не может работать дальше (класс VirtualMachineError) и так далее.

Несмотря на то, что в нашей программе мы никак не можем помочь этой проблеме, и приложение не может работать дальше (ну как может работать приложение, если стек вызовов переполнен или JVM не может дальше выполнять код?!); знание природы этих ошибок поможет вам предпринять некоторые действия, чтобы избежать этих ошибок в дальнейшем. Например, ошибки типа StackOverflowError и OutOfMemoryError могут быть следствием вашего некорректного кода.

Например, попробуем спровоцировать ошибку StackOverflowError

public static void main(String[] args) {

public static void methodA() {

private static void methodB() {

Получим такое сообщение об ошибке

Exception in thread «main» java.lang.StackOverflowError

at com.company.Main.methodB(Main.java:14)

at com.company.Main.methodA(Main.java:10)

at com.company.Main.methodB(Main.java:14)

at com.company.Main.methodA(Main.java:10)

at com.company.Main.methodB(Main.java:14)

at com.company.Main.methodA(Main.java:10)

at com.company.Main.methodB(Main.java:14)

at com.company.Main.methodA(Main.java:10)

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

Exception in thread «main» java.lang.OutOfMemoryError: Java heap space

at java.base/java.util.Arrays.copyOf(Arrays.java:3511)

at java.base/java.util.Arrays.copyOf(Arrays.java:3480)

at java.base/java.util.ArrayList.grow(ArrayList.java:237)

at java.base/java.util.ArrayList.grow(ArrayList.java:244)

at java.base/java.util.ArrayList.add(ArrayList.java:454)

at java.base/java.util.ArrayList.add(ArrayList.java:467)

at com.company.Main.main(Main.java:13)

Process finished with exit code 1

Ошибка VirtualMachineError может означать, что следует переустановить библиотеки Java.

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

Класс Exception описывает исключения, связанные непосредственно с работой программы. Такого рода исключения «решаемы» и их грамотная обработка позволит программе работать дальше в нормальном режиме.

В классе Exception описаны исключения двух видов: контролируемые исключения (checked exceptions) и неконтролируемые исключения (unchecked exceptions).

Неконтролируемые исключения содержатся в подклассе RuntimeException и его наследниках. Контролируемые исключения содержатся в остальных подклассах Exception.

В чем разница между контролируемыми и неконтролируемыми исключениями, мы узнаем позже, а теперь рассмотрим вопрос – а как же именно нам обрабатывать исключения?

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

  1. 1.

    с помощью связки try-catch;

  2. 2.

    с помощью ключевого слова throws в сигнатуре метода.

Рассмотрим оба метода поподробнее:

Способ 1. Связка try-catch

Этот способ кратко можно описать следующим образом.

Код, который теоретически может вызвать исключение, записывается в блоке try{}. Сразу за блоком try идет блок код catch{}, в котором содержится код, который будет выполнен в случае генерации исключения. В блоке finally{} содержится код, который будет выполнен в любом случае – произошло ли исключение или нет.

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

public static void main(String[] args) {

Scanner scanner = new Scanner(System.in);

System.out.println(«Введите первое число: «);

String firstNumber = scanner.nextLine();

System.out.println(«Введите второе число: «);

String secondNumber = scanner.nextLine();

a = Integer.parseInt(firstNumber);

b = Integer.parseInt(secondNumber);

System.out.println(«Результат: « + (a + b));

Первое, что нам нужно определить – и что является главным при работе с исключениями, КАКАЯ ИНСТРУКЦИЯ МОЖЕТ ПРИВЕСТИ К ВОЗНИКНОВЕНИЮ ИСКЛЮЧЕНИЯ?

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

a = Integer.parseInt(firstNumber);

b = Integer.parseInt(secondNumber);

в которых происходит преобразование ввода пользователя в целое число (метод parseInt() преобразует цифры в строке в число).

Почему здесь может возникнуть исключение? Потому что пользователь может ввести не число, а просто какой-то текст и тогда непонятно – что записывать в переменную a или b. И да, действительно, если пользователь введет некорректное значение, возникнет исключение в методе Integer.parseInt().

Итак, что мы можем сделать. «Опасный код» нужно поместить в блок try{}

Обратите внимание на синтаксис блока try. В самом простом случае это просто ключевое слово try, после которого идут парные фигурные скобки. Внутри этих скобок и заключается «опасный» код, который может вызвать исключение. Сразу после блока try должен идти блок catch().

a = Integer.parseInt(firstNumber);

b = Integer.parseInt(secondNumber);

} catch (NumberFormatException e) {

// сохранить текст ошибки в лог

System.out.println(«Одно или оба значения некорректны!»);

System.out.println(«Результат: « + (a + b));

Обратите внимание на синтаксис блока catch. После ключевого слова, в скобках описывается аргумент с именем e типа NumberFormatException.

Когда произойдет исключение, то система Java прервет выполнение инструкций в блоке try и передаст управление блоку catch и запишет в этот аргумент объект исключения, который сгенерировала Java-машина.

То есть, как только в блоке try возникнет исключение, то дальше инструкции в блоке try выполняться не будут! А сразу же начнут выполняться действия в блоке catch.

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

Блок catch сработает только в том случае, если указанный в скобках тип объекта исключения будет суперклассом или будет того же типа, что и объект исключения, который сгенерировала Java.

Например, если в нашем примере мы напишем код, который потенциально может выбросить исключение типа IOException, но не изменим блок catch

} catch (NumberFormatException e) {

// сохранить текст ошибки в лог

System.out.println(«Одно или оба значения некорректны!»);

тогда обработчик не будет вызван и исключение будет обработано стандартным обработчиком Java.

Способ 2. Использование ключевого слова throws

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

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

public static void main(String[] args) {

int a = getNumberFromConsole(«Введите первое число»);

int b = getNumberFromConsole(«Введите второе число»);

System.out.println(«Результат: « + (a + b));

public static int getNumberFromConsole(String message) {

Scanner scanner = new Scanner(System.in);

System.out.print(message + «: «);

String s = scanner.nextLine();

return Integer.parseInt(s);

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

  1. 1.

    обработка исключений может происходить централизованно однотипным способом (например, показ окошка с сообщением и с определенным текстом);

  2. 2.

    это не входит в нашу компетенцию как программиста – обработкой исключений занимается другой программист;

  3. 3.

    мы пишем только некоторую часть программы и непонятно – как будет обрабатывать исключение другой программист, который потом будет использовать наш код (например, мы пишем просто какую-то библиотеку, которая производит вычисления, и как будет выглядеть обработка – это не наше дело).

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

public static int getNumberFromConsole(String message) throws NumberFormatException {

Scanner scanner = new Scanner(System.in);

System.out.print(message + «: «);

String s = scanner.nextLine();

return Integer.parseInt(s);

Обратите внимание на расположение сигнатуру метода. Мы привыкли, что при объявлении метода сразу после скобок входных аргументов мы открываем фигурную скобку и записываем тело метода. Здесь же, после входных аргументов, мы пишем ключевое слово throws и потом указываем тип исключения, которое может быть сгенерировано в нашем методе. Если метод может выбрасывать несколько типов исключений, они записываются через запятую

public static void foo() throws NumberFormatException, ArithmeticException, IOException {

Тогда, в методе main мы должны написать примерно следующее

public static void main(String[] args) {

a = getNumberFromConsole(«Введите первое число»);

b = getNumberFromConsole(«Введите второе число»);

} catch (NumberFormatException e) {

// сохранить текст ошибки в лог

System.out.println(«Одно или оба значения некорректны!»);

System.out.println(«Результат: « + (a + b));

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

Отличия между контролируемыми и неконтролируемыми исключениями

Если вы вызываете метод, который выбрасывает checked исключение, то вы ОБЯЗАНЫ предусмотреть обработку возможного исключения, то есть связку try-catch.

Яркий пример checked исключения – класс IOException и его подклассы.

Рассмотрим пример – попробуем прочитать файл и построчно вывести его содержимое на экран консоли:

public static void main(String[] args) {

Path p = Paths.get(«c:\temp\file.txt»);

BufferedReader reader = Files.newBufferedReader(p);

while ((line = reader.readLine()) != null) {

System.out.println(line);

Как мы видим, компилятор не хочет компилировать наш код. Чем же он недоволен? У нас в коде происходит вызов двух методов – статического метода Files.newBufferedReader() и обычного метода BufferedReader.readLine().

Если посмотреть на сигнатуры этих методов то можно увидеть, что оба этих метода выбрасывают исключения типа IOException. Этот тип исключения относится к checked-исключению и поэтому, если вы вызываете эти методы, компилятор ТРЕБУЕТ от вас предусмотреть блок catch, либо в самом вашем методе указать throws IOException и, таким образом, передать обязанность обрабатывать исключение другому методу, который будет вызывать ваш.

Таким образом, «оборачиваем» наш код в блок try и пишем блок catch.

public static void main(String[] args) {

Path p = Paths.get(«c:\temp\file.txt»);

BufferedReader reader = Files.newBufferedReader(p);

while ((line = reader.readLine()) != null) {

System.out.println(line);

} catch (IOException e) {

System.out.println(«Ошибка при чтении файла!»);

Еще один способ — указать в сигнатуре метода, что он выбрасывает исключение типа IOException и переложить обязанность обработать ошибку в вызывающем коде

public static void main(String[] args) {

Path p = Paths.get(«c:\temp\file.txt»);

} catch (IOException e) {

System.out.println(«Ошибка при чтении файла!»);

public static void printFile(Path p) throws IOException {

BufferedReader reader = Files.newBufferedReader(p);

while ((line = reader.readLine()) != null) {

System.out.println(line);

Eсли метод выбрасывает checked-исключение, то проверка на наличие catch-блока происходит на этапе компиляции. И вы обязаны предусмотреть обработку исключения для checked-исключения.

Что касается unchecked-исключения, то обязательной обработки исключения нет – вы можете оставить подобные ситуации без обработки.

Зачем необходимо наличие двух видов исключений?

В большинстве языков существует всего лишь один тип исключений – unchecked. Некоторые языки, например, C#, в свое время отказались от checked-исключений.

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

С другой стороны, зачем нужно делать некоторые типы исключений checked? Почему просто не сделать все исключения unchecked и оставить решения об обработке исключений целиком на совести программиста?

В официальной документации написано, что unchecked-исключения – это те исключения, от которых программа «не может восстановиться», тогда как checked-исключения позволяют откатить некоторую операцию и повторить ее снова.

На самом деле, если вы посмотрите на различные типы unchecked-исключений, то вы увидите, что большинство их связаны с ошибками самого программиста. Выход за пределы массива, исключение нулевого указателя, деление на ноль – большинство из подобного рода исключений целиком лежат на совести программистов. Тогда мы можем сказать, что лучше программист пишет более хороший код, чем везде вставляет проверки на исключения.

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

Вы можете написать идеальный код, но потом вы отдадите приложение пользователю, а он введет название файла, которого нет или напишет неправильный IP для сокет-соединения. Таким образом, мы заранее должны быть готовыми к неверным действиям пользователя или к программным или аппаратным проблемам на его стороне и в обязательном порядке предусмотреть обработку возможных исключений.

Дополнительно об исключениях

Рассмотрим детально различные возможности механизма исключений, которые позволяют программисту максимально эффективно противодействовать исключениям:

Java позволяет вам для одного блока try предусмотреть несколько блоков catch, каждый из которых должен обрабатывать свой тип исключения

public static void foo() {

} catch (ArithmeticException e) {

// обработка арифметического исключения

} catch (IndexOutOfBoundsException e) {

// обработка выхода за пределы коллекции

} catch (IllegalArgumentException e) {

// обработка некорректного аргумента

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

Так как вы можете указать как точный класс, так и суперкласс, то если первым блоком будет блок для суперкласса – выполнится он. Например, исключение FileNotFoundException является подклассом IOException. И поэтому если вы первым поставите блок с IOException – он будет вызываться для всех подтипов исключений, в том числе и для FileNotFoundException и блок c FileNotFoundException никогда не выполнится.

public static void main(String[] args) {

Path p = Paths.get(«c:\temp\file.txt»);

} catch (IOException e) {

System.out.println(«Ошибка при чтении файла!»);

} catch (FileNotFoundException e) {

// данный блок никогда не будет вызван

public static void printFile(Path p) throws IOException {

BufferedReader reader = Files.newBufferedReader(p);

while ((line = reader.readLine()) != null) {

System.out.println(line);

Один блок для обработки нескольких типов исключений

Начиная с версии Java 7, вы можете использовать один блок catch для обработки исключений нескольких, не связанных друг с другом типов. Приведем пример

public static void foo() {

} catch (ArithmeticException | IllegalArgumentException | IndexOutOfBoundsException e) {

// три типа исключений обрабатываются одинаково

Как мы видим, один блок catch используется для обработки и типа IOException и NullPointerException и NumberFormaException.

Вы можете использовать вложенные блоки try, которые могут помещаться в других блоках try. После вложенного блока try обязательно идет блок catch

public static void foo() {

} catch (IllegalArgumentException e) {

// обработка вложенного блока try

} catch (ArithmeticException e) {

Выбрасывание исключения с помощью ключевого слова throw

С помощью ключевого слова throw вы можете преднамеренно «выбросить» определенный тип исключения.

public static void foo(int a) {

throw new IllegalArgumentException(«Аргумент не может быть отрицательным!»);

Кроме блока try и catch существует специальный блок finally. Его отличительная особенность – он гарантированно отработает, вне зависимости от того, будет выброшено исключение в блоке try или нет. Как правило, блок finally используется для того, чтобы выполнить некоторые «завершающие» операции, которые могли быть инициированы в блоке try.

public static void foo(int a) {

FileOutputStream fout = null;

File file = new File(«file.txt»);

fout = new FileOutputStream(file);

} catch (IOException e) {

// обработка исключения при записи в файл

} catch (IOException e) {

При любом развитии события в блоке try, код в блоке finally отработает в любом случае.

Блок finally отработает, даже если в try-catch присутствует оператор return.

Как правило, блок finally используется, когда мы в блоке try работаем с ресурсами (файлы, базы данных, сокеты и т.д.), когда по окончании блока try-catch мы освобождаем ресурсы. Например, допустим, в процессе работы программы возникло исключение, требующее ее преждевременного закрытия. Но в программе открыт файл или установлено сетевое соединение, а, следовательно, файл нужно закрыть, а соединение – разорвать. Для этого удобно использовать блок finally.

Блок try-with-resources является модификацией блока try. Данный блок позволяет автоматически закрывать ресурс после окончания работы блока try и является удобной альтернативой блоку finally.

public static void foo() {

Path p = Paths.get(«c:\temp\file.txt»);

try (BufferedReader reader = Files.newBufferedReader(p)) {

while ((line = reader.readLine()) != null)

System.out.println(line);

} catch (IOException e) {

Внутри скобок блока try объявляется один или несколько ресурсов, которые после отработки блока try-catch будут автоматически освобождены. Для этого объект ресурса должен реализовывать интерфейс java.lang.AutoCloseable.

Создание собственных подклассов исключений

Встроенные в Java исключения позволяют обрабатывать большинство распространенных ошибок. Тем не менее, вы можете создавать и обрабатывать собственные типы исключений. Для того, чтобы создать класс собственного исключения, достаточно определить как его произвольный от Exception или от RuntimeException (в зависимости от того, хотите ли вы использовать checked или unchecked – исключения).

Насчет создания рекомендуется придерживаться двух правил:

  1. 1.

    определитесь, исключения какого типа вы хотите использовать для собственных исключений (checked или unchecked) и старайтесь создавать исключения только этого типа;

  2. 2.

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

Плохие практики при обработке исключений

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

  1. 1.

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

  2. 2.

    Помещение в блок try всего тела метода. Следующий плохой прием используется, когда программист не хочет разбираться с кодом, который вызывает исключение и просто, опять же, реализует «заглушку». Этот прием очень «хорошо» сочетается с первым приемом. В блок try должен помещаться только тот код, который потенциально может вызвать исключение, а не всё подряд, т.к. лень обрабатывать исключения нормально.

  3. 3.

    Игнорирование исключения. Следующий плохой прием состоит в том, что мы просто игнорируем исключение и оставляем блок catch пустым. Программа должна реагировать на исключения и должна информировать пользователя и разработчика о том, что что-то пошло не так. Безусловно, исключение это не повод тут же закрывать приложение, а попытаться повторить то действие, которое привело к исключению (например, повторно указать название файла, попытаться открыть базу данных через время и т.д.). В любом случае, когда приложение в ответ на ошибку никак не реагирует – не выдает сообщение, но и не делает того, чего от нее ожидали – это самый плохой вариант.

  • Ошибка во время загрузки эксель
  • Ошибка во время загрузки конфиг файла видеопередатчика
  • Ошибка во время диктанта сканворд 6 букв
  • Ошибка во время выполнения программы python что значит
  • Ошибка во время выполнения программы informatics