Выключэнні Java і як з імі абыходзіцца

Як распрацоўшчык Java, вы павінны добра ведаць выключэнні і апрацоўку выключэнняў Java.

Гэты падручнік дае асноўныя веды, якімі павінен валодаць кожны праграміст пры працы з праграмамі Java. Для пачатку давайце пачнем з разумення таго, што менавіта з'яўляюцца выключэннямі Java.



Якія выключэнні Java

Праграма Java можа сутыкнуцца з праблемамі, у выніку якіх праграма рэзка спыняецца падчас яе выканання. Гэтыя праблемы называюцца выключэннямі.


Добры праграміст павінен умець распазнаваць памылкі, якія могуць узнікнуць падчас выканання, і прадастаўляць альтэрнатыўныя маршруты для праграмы ў выпадку такога выключэння. Гэтая практыка называецца апрацоўкай выключэнняў.

Цяпер вы можаце задацца пытаннем, навошта нам наогул патрэбна апрацоўка выключэнняў. Чаму б не напісаць праграмы, якія не будуць выклікаць выключэнняў?




Навошта нам патрэбна апрацоўка выключэнняў

Як аказалася, напісанне праграм, якія не будуць выкідваць выключэнні, не так проста, як гэта гучыць. Часцей за ўсё гэтыя непазбежныя памылкі выходзяць з-пад кантролю праграміста.



Праграмы, якія прымаюць увод карыстальніка, схільныя ўзнікненню выключэнняў з-за няправільнага ўводу, які прадастаўляе карыстальнік. Гэтак жа чытанне знешніх файлаў улічвае магчымасць перамяшчэння, перайменавання альбо выдалення знешняй крыніцай без ведама праграміста.

У такіх выпадках праграма павінна мець магчымасць вытанчана апрацоўваць выключэнне без спынення выканання.



Іерархія выключэнняў Java

Усе выключэнні ў Java павінны быць даччынай Exception класа, які сам з'яўляецца даччынай Throwable клас.


Два асноўныя падкласы Exception клас складаюць RuntimeException і IOException.



Выключэнне супраць памылкі

Яшчэ адзін дзіцячы клас Throwable клас - гэта Error клас. Аднак памылкі адрозніваюцца ад выключэнняў.

Памылкі паказваюць на праблемы, з якімі JVM можа сутыкнуцца падчас выканання. Гэтыя праблемы, як правіла, крытычныя і непапраўныя. Уцечкі памяці і праблемы з несумяшчальнасцю бібліятэк - распаўсюджаныя прычыны памылак у праграмах.

StackOverflowError і OutOfMemoryError два прыклады памылак Java.




Правераныя і неправераныя выключэнні

Мы можам падзяліць выключэнні Java на дзве асноўныя катэгорыі: праверана і неправерана выключэнні.

Вызначаныя выключэнні - гэта выключэнні, якія неабходна апрацаваць у праграме перад кампіляцыяй. Калі гэтыя выключэнні не апрацаваны, праграма не будзе скампілявана кампілятарам Java. Таму іх таксама называюць выключэннямі падчас кампіляцыі. IOExceptions з'яўляюцца добрымі прыкладамі правераных выключэнняў.

Неправераныя выключэнні - гэта выключэнні, якія кампілятар ігнаруе пры складанні праграмы. Звярталіся мы з гэтымі выключэннямі ў праграме ці не, не мае значэння, калі праграма складзена. Паколькі апрацоўка выключэнняў не накладаецца на гэтыя выключэнні, наша праграма можа сутыкнуцца з RuntimeExceptions што прыводзіць да спынення праграмы.

Усе класы, якія пашыраюць RuntimeException клас - гэта неправераныя выключэнні. Два прыклады такіх класаў: NullPointerException і ArrayIndexOutOfBoundsException.




Звычайна выкарыстоўваюцца метады ў класе выключэнняў

Мы разгледзім некалькі часта выкарыстоўваюцца метадаў у Java Exception клас:

  1. getMessage: вяртае паведамленне, якое змяшчае падрабязную інфармацыю пра выключэнне, якое адбылося.
  2. printStackTrace: вяртае след стэка ўзнікнення выключэння.
  3. toString: вяртае імя класа і паведамленне, якое вяртаецца з getMessage метад.


Як апрацоўваць выключэнні

Давайце паглядзім, як мы можам апрацоўваць выключэнні ў Java:

паспрабаваць-злавіць

Мы можам лавіць выключэнні і правільна апрацоўваць іх, выкарыстоўваючы паспрабаваць-злавіць блок у Java.

У гэтым сінтаксісе частка кода, схільная да выкіду выключэння, змяшчаецца ўнутр блока try, а блок catch / блокі ловіць кінутае выключэнне / выключэнні і апрацоўвае іх у адпаведнасці з логікай, якую мы прадстаўляем.


Асноўны сінтаксіс блока try-catch наступны:

try {
//exception-prone code } catch(Exception e) {
//error handling logic }

Пры такім падыходзе праграма не спыняе выкананне, калі праграма стварае выключэнне, замест гэтага яна хупава апрацоўваецца.

Мы ўбачым, як апрацоўваць IOExceptions кінуты FileReader клас у праграме Java.

Прыклад:

import java.io.FileReader; public class TryCatchBlockExample {
public static void main(String[] args) {

try {

FileReader file = new FileReader('source.txt');

file.read();
}
catch(Exception e) {

e.printStackTrace();
}
} }

Тут мы выкарыстоўвалі адзіны блок catch для апрацоўкі FileNotFoundException кідаецца пры стварэнні экземпляра FileReader клас і IOException кінуты read() метад FileReader клас.

Абодва гэтыя выключэнні - дзеці | | + + _ | клас.

Мы таксама можам выкарыстоўваць некалькі аператараў catch, каб злавіць розныя тыпы памылак, якія ўзнікаюць у кодзе ўнутры адзінай аперацыі try. У папярэднім прыкладзе мы можам выкарыстоўваць адзін блок catch, каб злавіць Exception і яшчэ адзін блок лову для FileNotFoundException як паказаны наступны фрагмент кода:

IOException

Калі выкінутае выключэнне супадае з выключэннем, апрацаваным першым выказваннем catch, яно апрацоўваецца логікай у першым выказванні catch.

Калі выключэнні не супадаюць, гэта перадаецца другой заяве catch. Калі ёсць больш за два выказванні catch, гэты працэс працягваецца, пакуль выключэнне не дасягне выразу catch, які ўлоўлівае яго тып.

Паколькі import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; public class TryCatchBlockExample {
public static void main(String[] args) {

try {

FileReader file = new FileReader('source.txt');

file.read();

file.close();
}
catch(FileNotFoundException e) {

e.printStackTrace();
}
catch(IOException e) {

e.printStackTrace();
}
} }
з'яўляецца падтыпам FileNotFoundException, выкарыстоўваючы другі выказнік catch, каб злавіць IOException не атрымаецца. Ён будзе апрацоўвацца ў першай заяве пра ўлоў і ніколі не дасягнуць другой заявы.

нататка:Абавязкова выкарыстоўваць па меншай меры адзін выраз catch з заявай try.

нарэшце

Калі мы выкарыстоўваем паспрабаваць-злавіць блок, каб злавіць выключэнні ў нашай праграме, ёсць выпадкі, калі мы хочам рэалізаваць пэўную логіку, нягледзячы на ​​тое, ці было злоўлена выключэнне. У такіх выпадках мы можам выкарыстоўваць a паспрабаваць-злавіць-нарэшце блок замест проста паспрабаваць-злавіць блок.

Затым код унутры FileNotFoundException заява рэалізуецца незалежна ад таго, ці адбываецца выключэнне. finally Заява заўсёды павінна прыходзіць у канцы блока try-catch-konačno.

Напрыклад, калі мы выкарыстоўваем finally класа, каб прачытаць файл, вельмі важна закрыць адкрыты файл у канцы апрацоўкі незалежна ад таго, узнікае выключэнне ці не. Каб пераканацца ў гэтым, мы можам змясціць код, каб закрыць файл у FileReader заява.

finally

Аднак, калі вы паспрабуеце скампіляваць прыведзены вышэй код, код не будзе скампіляваны з-за неапрацаванага import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; public class TryCatchFinallyBlockExample {
public static void main(String[] args) {
FileReader file = null;
try {

file = new FileReader('source.txt');

file.read();
}
catch(FileNotFoundException e) {

e.printStackTrace();
}
catch(IOException e) {

e.printStackTrace();
}
finally {

file.close();
}
} }
. Гэта таму, што IOException метад close() клас таксама можа кінуць FileReader. Такім чынам, мы павінны змясціць гэтую частку ў іншым спробным блоку, як гэта:

IOExceptions

кідае

Апрацоўка памылак з выкарыстаннем import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; public class TryCatchFinallyBlockExample {
public static void main(String[] args) {
FileReader file = null;

try {

file = new FileReader('source.txt');

file.read();
}
catch(FileNotFoundException e) {

e.printStackTrace();
}
catch(IOException e) {

e.printStackTrace();
}
finally {

try {


file.close();

}

catch(IOException e) {


e.printStackTrace();

}
}
} }
ключавое слова ў Java простае. На самай справе, пры такім падыходзе вы сапраўды не спраўляецеся з выключэннем у тым месцы, дзе яно адбываецца. Замест гэтага мы выкідваем выключэнне з бягучага метаду ў метад, які называецца бягучым метадам. Тады перадача памылкі становіцца адказнасцю знешняга метаду.

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

Прыклад:

FileReader

кінуць

У адрозненне ад іншых падыходаў у гэтым спісе, import java.io.FileReader; import java.io.IOException; public class ThrowsExample {
public void readFile throws IOException {
FileReader file = new FileReader('source.txt');
file.read();
file.close();
} }
ключавое слова не выкарыстоўваецца для апрацоўкі памылак. Але паколькі большасць людзей бянтэжыць throw ключавое слова з throw ключавое слова, мы думалі, што было б лепш абмеркаваць яго тут.

throws ключавое слова выкарыстоўваецца для відавочнага выклікання выключэння. Мы можам кінуць нядаўна зробленае выключэнне альбо выключэнне, якое было зафіксавана ўнутры метаду.

throw

Вызначаныя карыстальнікам выключэнні

У дадатак да выкарыстання ўбудаваных выключэнняў Java вы можаце вызначыць уласныя выключэнні. Вы можаце вызначыць іх як праверкі альбо як праверкі выключэнняў. Каб стварыць новае праверанае выключэнне, ваша новае выключэнне павінна пашырыць public class ThrowExample {
public void invalidate(int amount) throws Exception {
if (amount < 500) {

throw new Exception('Amount not sufficient');
}
} }
клас.

Каб стварыць нязламаны выключэнне, пашырыць Exception клас.

У наступным прыкладзе кода мы стварылі вызначанае карыстальнікам праверанае выключэнне:

RuntimeException

Цяпер мы можам выкарыстоўваць прыведзенае вышэй выключэнне ўнутры нашай логікі праграмы так:

public class InvalidLengthException extends Exception {
private int length;
private String message;
public InvalidLengthException(int length, String message) {
this.length=length;
this.message=message;
}
public int getAmount() {
return this.length;
}
public String getMessage() {
return this.message;
} }

Калі мы правяраем даўжыню радка, выкарыстоўваючы public class InputChecker {
private int minLength;
private int maxLength;
public InputChecker(int minLength, int maxLength) {
this.minLength=minLength;
this.maxLength=maxLength;
}
public void checkStringLength(String strInput) throws InvalidLengthException {
int strLength = strInput.length();
if (strLength maxLength){

throw new InvalidLengthException(strLength, 'Input should have maximum '+maxLength+' character');
}
} }
клас, ён выкліча InputChecker калі даўжыня радка ніжэй за мінімальную даўжыню альбо вышэй за максімальную.

InvalidLengthException

Калі мы запусцім прыведзены вышэй фрагмент кода, ён выдасць public class Main {
public static void main(String[] args) {
InputChecker ic = new InputChecker(2, 7);
try {

ic.checkStringLength('longer than the maximum length');
}
catch(InvalidLengthException e) {

e.printStackTrace();
}
} }
і мы атрымаем наступны вывад:

InvalidLengthException

Выснова

У гэтым уроку мы хутка і коратка пазнаёміліся з выключэннямі Java. Мы спадзяемся, што вы зараз добра разумееце, што такое выключэнні і як з імі змагацца ў вашай праграме Java.