При программировании часто возникают различного рода ошибки — ошибки программиста, пользователя, баги в сторонних библиотеках. Программа должна каким-то образом адекватно реагировать на их возникновение.
Например, пользователь решил поставить себе игру, управляемую акселерометром, а у него в устройстве этого самого акселерометра-то и нет. Программа должна объяснить это пользователю, а не закрываться с сообщением о неизвестной ошибке, иначе пользователь может решить, что криворукие кодеры не сделали поддержку его устройства и написать плохой отзыв.
Другой пример: юзер заполняет в приложении какую-нибудь анкету. Ввел кучу данных и вдруг записал что-то в неправильном формате. Программа падает, юзер недоволен. А можно было бы вывести сообщение и дать возможность пользователю дозаполнить анкету.
При программировании на android необработанное исключение вызывает сообщение об ошибке, и программа завершает свою работу.
Сначала научимся смотреть логи программы — для этого нужно включить LogCat с помощью Windows->ShowView->Other->LogCat
Для обработки исключений в Java используется механизм try-catch-finally. Создадим новый android проект со следующим кодом главного activity:
Параметром блока catch{} служит класс исключения, который мы пытаемся обработать. В данном примере мы пытаемся поймать все исключения класса Exception и его наследников.
Блок finally(может быть опущен) используется, когда при работе с кодом мы используем внешние ресурсы — файлы, соединения и др. Они должны быть как-то закрыты после выполнения кода. Поэтому инструкции, записанные в блоке finally, исполняются всегда, вне зависимости от того, возникло исключение или нет.
В данном случае в логах приложения мы увидим записи желтого цвета(обработанное исключение), выводящие информацию о том, конкретно где exception и вылез — в onCreate() в строке номер 15. Также там написан конкретный типа исключения — класс-наследник типа Exception, именуемый NullPointerException. Действительно, в 15-й строке мы сделали a.charAt(3) – обратились к непроинициализованной строке а. Если бы мы не использовали try-catch-finally, программа бы упала, а в лог информация записалась бы красным цветом.
Как уже было сказано, исключение — объект особого типа. Практически, при обработке следует понимать, какие exceptions могут возникнуть и обрабатывать их поочередно:
Некоторые классы исключений:
-RuntimeException
-NullPointerException – произведена какая-то операция с чем-то, равным null. Например, попытка обратиться к полю объекта до вызова его конструктора(объект еще не создан)
-IndexOutOfBoundException — ошибки выхода за пределы чего-либо
-ArrayIndexOutOfBoundsException – выход за пределы массива. Внимательно следуите за индексами, которые вы вычисляете
-StringIndexOutOfBoundException – аналогично предыдущему, только вместо массива выступает строка
-IllegalStateException – в функцию подан неккоректный параметр
-ArithmeticException – исключения, связанные с вычислениями
-DivisionByZeroException – целочисленное деление на 0
-ClassCastException – неправильно произведено преобразование классов
-IOException – ошибка при работе с внешним файлом(например, файл не найден)
-другие, в тч удобно собственные классы исключений наследовать от класса Exception
Все исключения в Java можно разделить на 2 большие группы — checkedExceptions и nonCheckedExceptions.
CheckedExceptions — такие исключения, при возникновении которых чего-то очень сильно опасного в программе происходить не должно и мы обязаны такое исключение обработать. В большинстве случаем причиной ошибки должны быть действия пользователя. Например, класс IOException является checkedException – если у нас ошибка при чтении файла, скорее всего, нам скормили какие-то некорректные данные. Особенностью таких исключений является то, что мы любой оператор, способный их бросить, должен оборачиваться в блок try-catch-(finally).
nonCheckedException, соответственно, являются обычно ошибками программистов или библиотек. Все классы, являющиеся наследниками RuntimeException (и он сам, конечно, тоже), являются nonCheckedExceptions, а остальные — наоборот.
Конечно, если мы будем проектировать свой класс, хорошо, если бы он тоже мог бросать исключения. Для этой цели в методе используется инструкция:
throw new <Класс исключения>(аргументы конструктора исключения).
При этом метод, в котором прямо или косвенно используется оператор throw, должен быть снабжен модификатором throws<Класс исключения>
Рассмотрим пример класса, бросающего checkedException. Он описывает отрезок с определенными координатами начала и конца, задаваемыми в конструкторе. Пусто он должен возвращать длину линии и ее ориентирный угол в радианах и градусах (ось х направлена вверх, ось у — вправо, ориентирный угол отсчитывается от оси х по часовой стрелке)
Если при определении ориентирного угла оба приращения координат равны 0, явно что-то нечисто и следует бросить исключение. Код класса отрезка:
Класс исключения:
Теперь изменим код onCreate на:
Убеждаемся, что исключение было брошено и в логах написано ровно то, что нужно.
Например, пользователь решил поставить себе игру, управляемую акселерометром, а у него в устройстве этого самого акселерометра-то и нет. Программа должна объяснить это пользователю, а не закрываться с сообщением о неизвестной ошибке, иначе пользователь может решить, что криворукие кодеры не сделали поддержку его устройства и написать плохой отзыв.
Другой пример: юзер заполняет в приложении какую-нибудь анкету. Ввел кучу данных и вдруг записал что-то в неправильном формате. Программа падает, юзер недоволен. А можно было бы вывести сообщение и дать возможность пользователю дозаполнить анкету.
При программировании на android необработанное исключение вызывает сообщение об ошибке, и программа завершает свою работу.
Сначала научимся смотреть логи программы — для этого нужно включить LogCat с помощью Windows->ShowView->Other->LogCat
Для обработки исключений в Java используется механизм try-catch-finally. Создадим новый android проект со следующим кодом главного activity:
package com.exc; import android.app.Activity; import android.os.Bundle; import android.util.Log; public class ExceptiontestActivity extends Activity { /** Called when the activity is first created. */ String a; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); try {//оборачиваем следующий код в блок обработки исключений a.charAt(3);//код, способный вызвать ошибку } catch (Exception e) { //здесь мы должны как-то обработать ошибку — известить пользователя, записать в лог информацию и тд. e.printStackTrace();//Выведем в лог информацию об ошибке — место возникновения, вплоть до конкретной строки кода, где возникло исключение } finally{ //Закрываем внешние ресурсы Log.d("app", "This is me, finally-block");//Операция записи в лог определенной строки(первый аргумент — тег записи, второй - сообщение) } setContentView(R.layout.main); } }В onCreate может возникнуть ошибка. Поэтому соответствующий код обернут в блог try{}, за которым следует блог catch{}, который будет исполняться, если возникло исключение.
Параметром блока catch{} служит класс исключения, который мы пытаемся обработать. В данном примере мы пытаемся поймать все исключения класса Exception и его наследников.
Блок finally(может быть опущен) используется, когда при работе с кодом мы используем внешние ресурсы — файлы, соединения и др. Они должны быть как-то закрыты после выполнения кода. Поэтому инструкции, записанные в блоке finally, исполняются всегда, вне зависимости от того, возникло исключение или нет.
В данном случае в логах приложения мы увидим записи желтого цвета(обработанное исключение), выводящие информацию о том, конкретно где exception и вылез — в onCreate() в строке номер 15. Также там написан конкретный типа исключения — класс-наследник типа Exception, именуемый NullPointerException. Действительно, в 15-й строке мы сделали a.charAt(3) – обратились к непроинициализованной строке а. Если бы мы не использовали try-catch-finally, программа бы упала, а в лог информация записалась бы красным цветом.
Как уже было сказано, исключение — объект особого типа. Практически, при обработке следует понимать, какие exceptions могут возникнуть и обрабатывать их поочередно:
try{ //Код } catch(<Первый тип исключений> e1){ //Обрабатываем первый тип } catch(<Второй тип исключений> e2){ //Обрабатываем второй тип. Конечно, если исключение первого типа возникло ранее, программа сюда уже не дойдет } finally{ //закрываем ресурсы }
Некоторые классы исключений:
-RuntimeException
-NullPointerException – произведена какая-то операция с чем-то, равным null. Например, попытка обратиться к полю объекта до вызова его конструктора(объект еще не создан)
-IndexOutOfBoundException — ошибки выхода за пределы чего-либо
-ArrayIndexOutOfBoundsException – выход за пределы массива. Внимательно следуите за индексами, которые вы вычисляете
-StringIndexOutOfBoundException – аналогично предыдущему, только вместо массива выступает строка
-IllegalStateException – в функцию подан неккоректный параметр
-ArithmeticException – исключения, связанные с вычислениями
-DivisionByZeroException – целочисленное деление на 0
-ClassCastException – неправильно произведено преобразование классов
-IOException – ошибка при работе с внешним файлом(например, файл не найден)
-другие, в тч удобно собственные классы исключений наследовать от класса Exception
Все исключения в Java можно разделить на 2 большие группы — checkedExceptions и nonCheckedExceptions.
CheckedExceptions — такие исключения, при возникновении которых чего-то очень сильно опасного в программе происходить не должно и мы обязаны такое исключение обработать. В большинстве случаем причиной ошибки должны быть действия пользователя. Например, класс IOException является checkedException – если у нас ошибка при чтении файла, скорее всего, нам скормили какие-то некорректные данные. Особенностью таких исключений является то, что мы любой оператор, способный их бросить, должен оборачиваться в блок try-catch-(finally).
nonCheckedException, соответственно, являются обычно ошибками программистов или библиотек. Все классы, являющиеся наследниками RuntimeException (и он сам, конечно, тоже), являются nonCheckedExceptions, а остальные — наоборот.
Конечно, если мы будем проектировать свой класс, хорошо, если бы он тоже мог бросать исключения. Для этой цели в методе используется инструкция:
throw new <Класс исключения>(аргументы конструктора исключения).
При этом метод, в котором прямо или косвенно используется оператор throw, должен быть снабжен модификатором throws<Класс исключения>
Рассмотрим пример класса, бросающего checkedException. Он описывает отрезок с определенными координатами начала и конца, задаваемыми в конструкторе. Пусто он должен возвращать длину линии и ее ориентирный угол в радианах и градусах (ось х направлена вверх, ось у — вправо, ориентирный угол отсчитывается от оси х по часовой стрелке)
Если при определении ориентирного угла оба приращения координат равны 0, явно что-то нечисто и следует бросить исключение. Код класса отрезка:
package com.exc; public class Line { private double x1; private double x2; private double y1; private double y2; private double dx; private double dy; private double dirAngle; public Line(double x1, double y1, double x2, double y2){ this.x1=x1; this.x2=x2; this.y1=y1; this.y2=y2; } public double dist(){ findDxAndDy();//определим приращения return Math.sqrt(dx*dx+dy*dy); //расчет по теореме Пифагора } public double findDirAngleInRads() throws LineException { findDirAngle();//определим ориентирный угол return dirAngle; } public double findDirAngleInDegrees() throws LineException { findDirAngle(); return dirAngle*180/Math.PI; //Переведем радианы в градусы и вернем результат } private void findDxAndDy() { dx=x2-x1; dy=y2-y1; } private void findDirAngle() throws LineException{ findDxAndDy(); if(dx==0 && dy==0){ //Исключительная ситуация throw new LineException("Координаты первой точки - Х="+x1+" Y="+y1+" - совпадают с координатами второй"); } dirAngle=Math.atan2(dy, dx);//Для определения ориентирного угла в радианах следует использовать функций Math.atan2(), так как она возвращает угол в соответствие со знаками приращений } }
Класс исключения:
package com.exc; public class LineException extends Exception {//пусть исключение будет проверяемым public LineException(String message){ super(message); } }
Теперь изменим код onCreate на:
super.onCreate(savedInstanceState); try { Line line=new Line(4,2,4,2); Log.d("app", line.findDirAngleInDegrees()+""); } catch (LineException e) { Log.d("app", e.getMessage()); } finally{ Log.d("app", "This is me, the finally-block"); } setContentView(R.layout.main);
Убеждаемся, что исключение было брошено и в логах написано ровно то, что нужно.
Комментариев нет:
Отправить комментарий