JavaRush /Java Blog /Random-TL /Mga pagbubukod sa Java: paghuli at paghawak

Mga pagbubukod sa Java: paghuli at paghawak

Nai-publish sa grupo
Kamusta! Ayaw kong i-break ito sa iyo, ngunit malaking bahagi ng trabaho ng isang programmer ang pagharap sa mga error. At kadalasan - sa kanilang sarili. Nagkataon lang na walang taong hindi nagkakamali. At wala ring ganitong mga programa. Siyempre, ang pangunahing bagay kapag nagtatrabaho sa isang error ay upang maunawaan ang sanhi nito. At maaaring mayroong isang buong grupo ng mga dahilan para sa ganoon sa programa. Sa isang punto, ang mga tagalikha ng Java ay nahaharap sa isang tanong: ano ang gagawin sa mga potensyal na error na ito sa mga programa? Ang ganap na pag-iwas sa kanila ay hindi makatotohanan. Ang mga programmer ay maaaring magsulat ng isang bagay na imposibleng isipin :) Nangangahulugan ito na kinakailangan na bumuo sa wika ng isang mekanismo para sa pagharap sa mga pagkakamali. Sa madaling salita, kung may naganap na error sa programa, kailangan ng script para sa karagdagang trabaho. Ano ba talaga ang dapat gawin ng program kapag may naganap na error? Ngayon ay makikilala natin ang mekanismong ito. At ito ay tinatawag na “Exceptions .

Ano ang isang pagbubukod sa Java

Ang eksepsiyon ay ilang kakaiba, hindi planadong sitwasyon na naganap sa panahon ng pagpapatakbo ng programa. Maaaring mayroong maraming mga halimbawa ng mga pagbubukod sa Java. Halimbawa, nagsulat ka ng isang code na nagbabasa ng teksto mula sa isang file at ipinapakita ang unang linya sa console.
public class Main {

   public static void main(String[] args) throws IOException {
       BufferedReader reader = new BufferedReader(new FileReader("C:\\Users\\Username\\Desktop\\test.txt"));
       String firstString = reader.readLine();
       System.out.println(firstString);
   }
}
Ngunit ang gayong file ay hindi umiiral! Ang resulta ng programa ay magiging eksepsiyon - FileNotFoundException. Konklusyon:

Exception in thread "main" java.io.FileNotFoundException: C:\Users\Username\Desktop\test.txt (Системе не удается найти указанный путь)
Ang bawat pagbubukod ay kinakatawan ng isang hiwalay na klase sa Java. Lahat ng exception classes ay nagmula sa isang karaniwang "ancestor" - ang parent class Throwable. Ang pangalan ng klase ng pagbubukod ay karaniwang maikling sumasalamin sa dahilan ng paglitaw nito:
  • FileNotFoundException(hindi nahanap ang file)
  • ArithmeticException(exception kapag nagsasagawa ng math operation)
  • ArrayIndexOutOfBoundsException(ang bilang ng array cell ay tinukoy na lampas sa haba nito). Halimbawa, kung susubukan mong i-output ang cell array[23] sa console para sa array array na 10 ang haba.
Mayroong halos 400 ganoong klase sa Java! Bakit ang dami? Tiyak na gawin itong mas maginhawa para sa mga programmer na makipagtulungan sa kanila. Isipin: nagsulat ka ng isang programa, at kapag tumakbo ito, naglalabas ito ng isang pagbubukod na ganito ang hitsura:
Exception in thread "main"
Uh-uh :/ Walang malinaw. Anong uri ng pagkakamali ito at kung saan ito nanggaling ay hindi malinaw. Walang kapaki-pakinabang na impormasyon. Ngunit salamat sa iba't ibang klase, nakukuha ng programmer ang pangunahing bagay para sa kanyang sarili - ang uri ng error at ang posibleng dahilan nito, na nakapaloob sa pangalan ng klase. Pagkatapos ng lahat, ito ay isang ganap na kakaibang bagay na makikita sa console:
Exception in thread "main" java.io.FileNotFoundException: C:\Users\Username\Desktop\test.txt (Системе не удается найти указанный путь)
Kaagad na nagiging malinaw kung ano ang maaaring problema at "saang direksyon dapat humukay" upang malutas ang problema! Ang mga pagbubukod, tulad ng anumang mga pagkakataon ng mga klase, ay mga bagay.

Paghuli at Paghawak ng mga Exception

Upang gumana sa mga pagbubukod sa Java, mayroong mga espesyal na bloke ng code: try, catchat finally. Mga pagbubukod: pagharang at pagproseso - 2Ang code kung saan inaasahan ng programmer ang mga pagbubukod na magaganap ay inilalagay sa isang bloke try. Hindi ito nangangahulugan na ang isang pagbubukod ay kinakailangang mangyari sa lokasyong ito. Nangangahulugan ito na maaari itong mangyari doon, at alam ito ng programmer. Ang uri ng error na inaasahan mong matatanggap ay inilalagay sa isang bloke catch("catch"). Dito rin inilalagay ang lahat ng code na kailangang i-execute kung may exception. Narito ang isang halimbawa:
public static void main(String[] args) throws IOException {
   try {
       BufferedReader reader = new BufferedReader(new FileReader("C:\\Users\\Username\\Desktop\\test.txt"));

       String firstString = reader.readLine();
       System.out.println(firstString);
   } catch (FileNotFoundException e) {

       System.out.println("Error! File not found!");
   }
}
Konklusyon:

Ошибка! Файл не найден!
Inilagay namin ang aming code sa dalawang bloke. Sa unang block, inaasahan namin na maaaring mangyari ang isang error na "Hindi nahanap ang file." Ito ay isang bloke try. Sa pangalawa, sasabihin namin sa programa kung ano ang gagawin kung may nangyaring error. Bukod dito, mayroong isang tiyak na uri ng error - FileNotFoundException. Kung ipapasa namin catchang isa pang klase ng exception sa mga block bracket, hindi ito mahuhuli.
public static void main(String[] args) throws IOException {
   try {
       BufferedReader reader = new BufferedReader(new FileReader("C:\\Users\\Username\\Desktop\\test.txt"));
       String firstString = reader.readLine();
       System.out.println(firstString);
   } catch (ArithmeticException e) {

       System.out.println("Error! File not found!");
   }
}
Konklusyon:

Exception in thread "main" java.io.FileNotFoundException: C:\Users\Username\Desktop\test.txt (Системе не удается найти указанный путь)
Ang code sa block catchay hindi gumana dahil "na-configure" namin ang block na ito upang maharang ArithmeticException, at ang code sa block tryay nagtapon ng isa pang uri - FileNotFoundException. Hindi kami sumulat ng script para sa FileNotFoundException, kaya ipinapakita ng program sa console ang impormasyon na ipinapakita bilang default para sa FileNotFoundException. Dito kailangan mong bigyang pansin ang 3 bagay. Una. Sa sandaling magkaroon ng exception sa anumang linya ng code sa isang try block, ang code pagkatapos nito ay hindi na isasagawa. Ang pagpapatupad ng programa ay agad na "tumalon" sa block catch. Halimbawa:
public static void main(String[] args) {
   try {
       System.out.println("Divide a number by zero");
       System.out.println(366/0);//this line of code will throw an exception

       System.out.println("This");
       System.out.println("code");
       System.out.println("Not");
       System.out.println("will");
       System.out.println("done!");

   } catch (ArithmeticException e) {

       System.out.println("The program jumped to the catch block!");
       System.out.println("Error! You can't divide by zero!");
   }
}
Konklusyon:

Делим число на ноль 
Программа перепрыгнула в блок catch! 
Ошибка! Нельзя делить на ноль! 
Sa block trysa pangalawang linya, sinubukan naming hatiin ang isang numero sa 0, na nagresulta sa isang pagbubukod ArithmeticException. Pagkatapos nito, ang mga linya 6-10 ng block tryay hindi na isasagawa. Gaya ng sinabi namin, agad na sinimulan ng programa ang pagsasagawa ng block catch. Pangalawa. Maaaring may ilang mga bloke catch. Kung ang code sa isang bloke tryay hindi maaaring magtapon ng isa, ngunit ilang uri ng mga pagbubukod, maaari mong isulat ang iyong sariling bloke para sa bawat isa sa kanila catch.
public static void main(String[] args) throws IOException {
   try {
       BufferedReader reader = new BufferedReader(new FileReader("C:\\Users\\Username\\Desktop\\test.txt"));

       System.out.println(366/0);
       String firstString = reader.readLine();
       System.out.println(firstString);
   } catch (FileNotFoundException e) {

       System.out.println("Error! File not found!");

   } catch (ArithmeticException e) {

       System.out.println("Error! Division by 0!");

   }
}
Sa halimbawang ito nagsulat kami ng dalawang bloke catch. Kung , tryay nangyayari sa block FileNotFoundException, ang unang block ay isasagawa catch. Kung mangyari ArithmeticException, isasagawa ang pangalawa. Maaari kang magsulat ng hindi bababa sa 50 na mga bloke catch. Ngunit, siyempre, mas mahusay na huwag magsulat ng code na maaaring magtapon ng 50 iba't ibang uri ng mga error :) Pangatlo. Paano mo malalaman kung anong mga pagbubukod ang maaaring itapon ng iyong code? Well, maaari mong, siyempre, hulaan ang tungkol sa ilan, ngunit imposibleng panatilihin ang lahat sa iyong ulo. Samakatuwid, alam ng Java compiler ang tungkol sa mga pinakakaraniwang eksepsiyon at alam kung anong mga sitwasyon ang maaaring mangyari. Halimbawa, kung sumulat ka ng code at alam ng compiler na 2 uri ng mga exception ang maaaring mangyari sa panahon ng operasyon nito, hindi magko-compile ang iyong code hanggang sa mahawakan mo ang mga ito. Makakakita tayo ng mga halimbawa nito sa ibaba. Ngayon tungkol sa paghawak ng exception. Mayroong 2 paraan upang iproseso ang mga ito. Nakilala na namin ang una - ang pamamaraan ay maaaring hawakan ang pagbubukod nang nakapag-iisa sa bloke catch(). Mayroong pangalawang opsyon - ang pamamaraan ay maaaring magtapon ng isang pagbubukod sa stack ng tawag. Ano ang ibig sabihin nito? Halimbawa, sa aming klase mayroon kaming isang pamamaraan - ang parehong paraan printFirstString()- na nagbabasa ng isang file at ipinapakita ang unang linya nito sa console:
public static void printFirstString(String filePath) {

   BufferedReader reader = new BufferedReader(new FileReader(filePath));
   String firstString = reader.readLine();
   System.out.println(firstString);
}
Sa kasalukuyan, hindi nag-compile ang aming code dahil mayroon itong mga hindi nahawakang exception. Sa linya 1 ipinapahiwatig mo ang landas patungo sa file. Alam ng compiler na ang naturang code ay madaling humantong sa FileNotFoundException. Sa linya 3 nabasa mo ang teksto mula sa file. Sa prosesong ito, madaling mangyari IOExceptionang isang error sa panahon ng input-output (Input-Output) . Ngayon ang compiler ay nagsasabi sa iyo, “Dude, hindi ko aaprubahan ang code na ito o i-compile ito hanggang sa sabihin mo sa akin kung ano ang dapat kong gawin kung mangyari ang isa sa mga exception na ito. At tiyak na maaaring mangyari ang mga ito batay sa code na iyong isinulat!” . Walang mapupuntahan, kailangan mong iproseso pareho! Ang unang opsyon sa pagproseso ay pamilyar na sa amin: kailangan naming ilagay ang aming code sa isang bloke tryat magdagdag ng dalawang bloke catch:
public static void printFirstString(String filePath) {

   try {
       BufferedReader reader = new BufferedReader(new FileReader(filePath));
       String firstString = reader.readLine();
       System.out.println(firstString);
   } catch (FileNotFoundException e) {
       System.out.println("Error, file not found!");
       e.printStackTrace();
   } catch (IOException e) {
       System.out.println("Error while inputting/outputting data from file!");
       e.printStackTrace();
   }
}
Ngunit hindi lamang ito ang pagpipilian. Maiiwasan natin ang pagsusulat ng script para sa error sa loob ng pamamaraan, at itapon lang ang exception sa itaas. Ginagawa ito gamit ang keyword throws, na nakasulat sa deklarasyon ng pamamaraan:
public static void printFirstString(String filePath) throws FileNotFoundException, IOException {
   BufferedReader reader = new BufferedReader(new FileReader(filePath));
   String firstString = reader.readLine();
   System.out.println(firstString);
}
Pagkatapos ng salita, throwsinilista namin, na pinaghihiwalay ng mga kuwit, ang lahat ng uri ng mga pagbubukod na maaaring itapon ng pamamaraang ito sa panahon ng operasyon. Bakit ito ginagawa? Ngayon, kung nais ng isang tao sa programa na tawagan ang pamamaraan printFirstString(), kakailanganin niyang ipatupad ang pagbubukod sa paghawak sa kanyang sarili. Halimbawa, sa isa pang bahagi ng programa, ang isa sa iyong mga kasamahan ay sumulat ng isang pamamaraan kung saan tinatawag nito ang iyong pamamaraan printFirstString():
public static void yourColleagueMethod() {

   //...your colleague's method does something

   //...and at one moment calls your printFirstString() method with the file it needs
   printFirstString("C:\\Users\\Eugene\\Desktop\\testFile.txt");
}
Error, hindi nag-compile ang code! printFirstString()Hindi kami nagsulat ng script sa paghawak ng error sa pamamaraan . Samakatuwid, ang gawain ay nahuhulog sa mga balikat ng mga gagamit ng pamamaraang ito. Ibig sabihin, yourColleagueMethod()nahaharap na ngayon ang pamamaraan sa parehong 2 opsyon: dapat itong iproseso ang parehong mga pagbubukod na "lumipad" dito gamit ang try-catch, o ipasa pa ang mga ito.
public static void yourColleagueMethod() throws FileNotFoundException, IOException {
   //...the method does something

   //...and at one moment calls your printFirstString() method with the file it needs
   printFirstString("C:\\Users\\Eugene\\Desktop\\testFile.txt");
}
Sa pangalawang kaso, ang pagproseso ay mahuhulog sa mga balikat ng susunod na paraan sa stack - ang tatawag sa yourColleagueMethod(). Iyon ang dahilan kung bakit ang naturang mekanismo ay tinatawag na "paghahagis ng isang pagbubukod pataas", o "pagpasa sa itaas". Kapag naghagis ka ng mga pagbubukod gamit ang throws, nag-iipon ang code. Sa sandaling ito, tila sinasabi ng compiler: "Okay, okay. Ang iyong code ay naglalaman ng isang grupo ng mga potensyal na pagbubukod, ngunit isasama ko pa rin ito. Babalik tayo sa usapan na ito!" At kapag tumawag ka ng isang paraan sa isang lugar sa program na hindi nakayanan ang mga eksepsiyon nito, tinutupad ng compiler ang pangako nito at muling ipinapaalala sa iyo ang tungkol sa mga ito. Sa wakas, pag-uusapan natin ang tungkol sa block finally(paumanhin ang pun). Ito ang huling bahagi ng exception sa paghawak ng triumvirate try-catch-finally. Ang kakaiba nito ay na ito ay naisakatuparan sa ilalim ng anumang senaryo ng pagpapatakbo ng programa.
public static void main(String[] args) throws IOException {
   try {
       BufferedReader reader = new BufferedReader(new FileReader("C:\\Users\\Username\\Desktop\\test.txt"));

       String firstString = reader.readLine();
       System.out.println(firstString);
   } catch (FileNotFoundException e) {
       System.out.println("Error! File not found!");
       e.printStackTrace();
   } finally {
       System.out.println("And here is the finally block!");
   }
}
Sa halimbawang ito, ang code sa loob ng block finallyay isinasagawa sa parehong mga kaso. Kung ang code sa block tryay ganap na naisakatuparan at hindi naglalabas ng exception, ang block ay gagana sa dulo finally. Kung ang code sa loob tryay nagambala at ang programa ay tumalon sa block catch, pagkatapos na ang code sa loob ay naisakatuparan catch, ang block ay pipiliin pa rin finally. Bakit kailangan ito? Ang pangunahing layunin nito ay upang maisagawa ang kinakailangang bahagi ng code; ang bahaging iyon na dapat tapusin anuman ang mga pangyayari. Halimbawa, madalas nitong pinapalaya ang ilang mapagkukunang ginagamit ng programa. Sa aming code, nagbubukas kami ng stream upang basahin ang impormasyon mula sa isang file at ipasa ito sa isang BufferedReader. Ang atin readeray kailangang sarado at ang mga mapagkukunan ay malaya. Dapat itong gawin sa anumang kaso: hindi mahalaga kung gumagana ang programa tulad ng inaasahan o magtapon ng isang pagbubukod. Maginhawang gawin ito sa isang bloke finally:
public static void main(String[] args) throws IOException {

   BufferedReader reader = null;
   try {
       reader = new BufferedReader(new FileReader("C:\\Users\\Username\\Desktop\\test.txt"));

       String firstString = reader.readLine();
       System.out.println(firstString);
   } catch (FileNotFoundException e) {
       e.printStackTrace();
   } finally {
       System.out.println("And here is the finally block!");
       if (reader != null) {
           reader.close();
       }
   }
}
Ngayon ay lubos na kaming nakatitiyak na aming pinangangalagaan ang mga okupado na mapagkukunan, anuman ang mangyari habang tumatakbo ang programa :) Hindi lang iyon ang kailangan mong malaman tungkol sa mga pagbubukod. Ang paghawak ng error ay isang napakahalagang paksa sa programming: higit sa isang artikulo ang nakatuon dito. Sa susunod na aralin, malalaman natin kung anong mga uri ng exception ang mayroon at kung paano gumawa ng sarili mong exception :) See you there!
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION