CodeGym /Java Blog /Random /Mga pagbubukod: paghuli at paghawak
John Squirrels
Antas
San Francisco

Mga pagbubukod: paghuli at paghawak

Nai-publish sa grupo
Hi! Ayaw kong banggitin ito, ngunit isang malaking bahagi ng gawain ng isang programmer ang pagharap sa mga error. Kadalasan, ang sarili niya. Wala namang taong hindi nagkakamali. At wala ring ganitong mga programa. Mga pagbubukod: paghuli at paghawak - 1 Siyempre, kapag nakikitungo sa isang error, ang pangunahing bagay ay upang maunawaan ang sanhi nito. At maraming bagay ang maaaring magdulot ng mga bug sa isang programa. Sa ilang mga punto, ang mga tagalikha ng Java ay nagtanong sa kanilang sarili kung ano ang dapat gawin sa mga malamang na error sa programming? Ang ganap na pag-iwas sa kanila ay hindi makatotohanan, ang mga programmer ay may kakayahang magsulat ng mga bagay na hindi mo maisip. :) Kaya, kailangan nating bigyan ang wika ng isang mekanismo para sa pagtatrabaho sa mga error. Sa madaling salita, kung may error sa iyong programa, kailangan mo ng ilang uri ng script para sa susunod na gagawin. Ano nga ba ang dapat gawin ng isang programa kapag may naganap na error? Ngayon ay makikilala natin ang mekanismong ito. Tinatawag itong " mga pagbubukod sa Java ".

Ano ang exception?

Ang pagbubukod ay isang pambihirang, hindi planadong sitwasyon na nangyayari habang tumatakbo ang isang programa. Maraming exception. Halimbawa, nagsulat ka ng code na nagbabasa ng teksto mula sa isang file, at ipinapakita ang unang linya.

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 paano kung walang ganoong file! Ang programa ay bubuo ng isang pagbubukod: FileNotFoundException. Output: Exception sa thread na "main" java.io.FileNotFoundException: C:\Users\Username\Desktop\test.txt (Hindi mahanap ng system ang tinukoy na path) Sa Java, ang bawat exception ay kinakatawan ng isang hiwalay na klase. Lahat ng mga exception class na ito ay nagmula sa isang karaniwang "ancestor"—ang Throwableparent class. Ang pangalan ng klase ng pagbubukod ay karaniwang maigsi na nagpapakita kung bakit nangyari ang pagbubukod:
  • FileNotFoundException(hindi nahanap ang file)

  • ArithmeticException(isang exception ang naganap habang nagsasagawa ng mathematical operation)

  • ArrayIndexOutOfBoundsException(ang index ay lampas sa mga hangganan ng array). Halimbawa, nangyayari ang pagbubukod na ito kung susubukan mong ipakita ang posisyon 23 ng isang array na may 10 elemento lamang.
Sa kabuuan, ang Java ay may halos 400 ganoong klase! Bakit ang dami? Upang gawing mas maginhawa para sa mga programmer na magtrabaho kasama. Isipin ito: sumulat ka ng isang programa, at habang tumatakbo ito ay bumubuo ito ng isang pagbubukod na ganito ang hitsura:

Exception in thread "main"
Uhhhh. :/ Hindi yan nakakatulong masyado. Hindi malinaw kung ano ang ibig sabihin ng error o kung saan ito nanggaling. Walang kapaki-pakinabang na impormasyon dito. Ngunit ang malaking iba't ibang klase ng exception sa Java ay nagbibigay sa programmer kung ano ang pinakamahalaga: ang uri ng error at ang posibleng dahilan nito (naka-embed sa pangalan ng klase). Ito ay medyo ibang bagay upang makita

Exception in thread "main" java.io.FileNotFoundException: C:\Users\Username\Desktop\test.txt (The system cannot find the specified path)
Ito ay kaagad na malinaw kung ano ang maaaring maging problema at kung saan magsisimula sa paghuhukay upang malutas ang problema! Ang mga pagbubukod, tulad ng mga pagkakataon ng anumang klase, ay mga bagay.

Paghuli at paghawak ng mga pagbubukod

Ang Java ay may mga espesyal na bloke ng code para sa pagtatrabaho sa mga pagbubukod: try, catchat finally. Mga pagbubukod: paghuli at paghawak - 2 Ang code kung saan naniniwala ang programmer na maaaring mangyari ang isang pagbubukod ay inilalagay sa tryblock. Hindi ibig sabihin nito na magkakaroon ng exception dito. Nangangahulugan ito na maaaring mangyari ito dito, at alam ng programmer ang posibilidad na ito. Ang uri ng error na inaasahan mong mangyari ay inilalagay sa catchblock. Naglalaman din ito ng lahat ng code na dapat isagawa kung may nangyaring pagbubukod. 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!");
   }
}
Output: Error! Hindi nahanap ang file! Inilagay namin ang aming code sa dalawang bloke. Sa unang block, inaasahan namin na maaaring mangyari ang isang error na "File not found." Ito ang tryblock. Sa pangalawa, sasabihin namin sa programa kung ano ang gagawin kung may nangyaring error. At ang partikular na uri ng error: FileNotFoundException. Kung maglalagay kami ng ibang klase ng exception sa mga panaklong ng catchblock, FileNotFoundExceptionhindi 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!");
   }
}
Output: Exception sa thread na "main" java.io.FileNotFoundException: C:\Users\Username\Desktop\test.txt (Hindi mahanap ng system ang tinukoy na path) Hindicatch tumakbo ang code sa block, dahil "na-configure" namin ang block na ito upang mahuli ArithmeticException, at ang code sa tryblock ay naghagis ng ibang uri: FileNotFoundException. Hindi kami sumulat ng anumang code na hahawakan FileNotFoundException, kaya ipinapakita ng programa ang default na impormasyon para sa FileNotFoundException. Dito kailangan mong bigyang pansin ang tatlong bagay. Numero uno. Kapag nagkaroon ng exception sa ilang linya sa tryblock, ang code na kasunod ay hindi isasagawa. Ang pagpapatupad ng programa ay agad na "tumalon" sa catchbloke. Halimbawa:

public static void main(String[] args) {
   try {
       System.out.println("Divide 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("will not");
       System.out.println("be");
       System.out.println("executed!");

   } catch (ArithmeticException e) {

       System.out.println("The program jumped to the catch block!");
       System.out.println("Error! You can't divide by zero!");
   }
}
Output: Divide by zero Ang programa ay tumalon sa catch block! Error! Hindi mo maaaring hatiin sa zero! Sa pangalawang linya ng trybloke, sinusubukan naming hatiin sa 0, na nagreresulta sa isang ArithmeticException. Dahil dito, ang mga linya 3-9 ng tryblock ay hindi isasagawa. Tulad ng sinabi namin, agad na sinisimulan ng programa ang pagpapatupad ng catchblock. Bilang dalawa. Maaaring may ilang catchmga bloke. Kung ang code sa tryblock ay maaaring maghagis ng hindi isa, ngunit maraming iba't ibang uri ng mga pagbubukod, maaari kang magsulat ng isang catchbloke para sa bawat isa sa kanila.

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, sumulat kami ng dalawang catchbloke. Kung may FileNotFoundExceptionnangyari sa tryblock, ang unang catchblock ay isasagawa. Kung may ArithmeticExceptionnangyari, ang pangalawang bloke ay isasagawa. Maaari kang magsulat ng 50 catchbloke kung gusto mo. Siyempre, mas mabuting huwag magsulat ng code na maaaring maghagis ng 50 iba't ibang uri ng mga pagbubukod. :) Pangatlo. Paano mo malalaman kung aling mga pagbubukod ang maaaring itapon ng iyong code? Well, maaari mong hulaan ang ilan sa mga ito, ngunit imposible para sa iyo na panatilihin ang lahat sa iyong ulo. Ang Java compiler samakatuwid ay alam ang pinakakaraniwang mga pagbubukod at ang mga sitwasyon kung saan maaaring mangyari ang mga ito. Halimbawa, kung magsusulat ka ng code na alam ng compiler na maaaring magtapon ng dalawang uri ng mga exception, hindi magko-compile ang iyong code hanggang sa mahawakan mo ang mga ito. Makakakita tayo ng mga halimbawa nito sa ibaba. Ngayon ang ilang mga salita tungkol sa paghawak ng exception. Mayroong 2 paraan upang mahawakan ang mga pagbubukod. Nakatagpo na namin ang una: ang pamamaraan ay maaaring hawakan ang pagbubukod mismo sa isang catch()bloke. Mayroong pangalawang opsyon: ang pamamaraan ay maaaring muling ihagis ang pagbubukod sa stack ng tawag. Anong ibig sabihin niyan? Halimbawa, mayroon kaming isang klase na may parehong printFirstString()pamamaraan, na nagbabasa ng isang file at ipinapakita ang unang linya nito:

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, tinukoy mo ang landas patungo sa file. Alam ng compiler na ang naturang code ay madaling makagawa ng isang FileNotFoundException. Sa linya 3, nabasa mo ang teksto mula sa file. Ang prosesong ito ay madaling magresulta sa isang IOException(input/output error). Ngayon, sasabihin sa iyo ng compiler, "Dude, hindi ko aaprubahan ang code na ito at hindi ko ito isasama 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 isinulat mo !" Walang paraan upang makalibot dito: kailangan mong pangasiwaan ang pareho! Alam na natin ang tungkol sa unang paraan ng paghawak ng exception: kailangan nating ilagay ang ating code sa isang trybloke at magdagdag ng dalawang catchbloke:

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("File input/output error!");
       e.printStackTrace();
   }
}
Ngunit hindi lamang ito ang pagpipilian. Maaari lang nating itapon ang exception nang mas mataas sa halip na magsulat ng error-handling code sa loob ng pamamaraan. Ginagawa ito gamit ang keyword throwssa 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 keyword throws, ipinapahiwatig namin ang isang listahan na pinaghihiwalay ng kuwit ng lahat ng uri ng mga pagbubukod na maaaring itapon ng pamamaraan. Bakit? Ngayon, kung may gustong tumawag sa printFirstString()pamamaraan sa programa, siya (hindi ikaw) ang kailangang magpatupad ng exception handling. Halimbawa, ipagpalagay na sa ibang lugar sa programa ang isa sa iyong mga kasamahan ay nagsulat ng isang pamamaraan na tumatawag sa iyong printFirstString()pamamaraan:

public static void yourColleagueMethod() {

   // Your colleague's method does something

   //...and then calls your printFirstString() method with the file it needs
   printFirstString("C:\\Users\\Henry\\Desktop\\testFile.txt");
}
Nagkakamali kami! Ang code na ito ay hindi mag-compile! Hindi kami sumulat ng exception-handling code sa printFirstString()pamamaraan. Bilang isang resulta, ang gawaing ito ay nahuhulog na ngayon sa mga balikat ng mga gumagamit ng pamamaraan. Sa madaling salita, ang methodWrittenByYourColleague()pamamaraan ay mayroon na ngayong parehong 2 mga pagpipilian: dapat itong gumamit ng isang try-catchbloke upang mahawakan ang parehong mga pagbubukod, o muling itapon ang mga ito.

public static void yourColleagueMethod() throws FileNotFoundException, IOException {
   // The method does something

   //...and then calls your printFirstString() method with the file it needs
   printFirstString("C:\\Users\\Henry\\Desktop\\testFile.txt");
}
Sa pangalawang kaso, ang susunod na paraan sa call stack—ang tumatawag methodWrittenByYourColleague()—ay kailangang pangasiwaan ang mga exception. Iyon ang dahilan kung bakit tinatawag namin itong "paghahagis o pagpasa sa pagbubukod". Kung magtapon ka ng mga pagbubukod pataas gamit ang keyword throws, mag-iipon ang iyong code. Sa puntong ito, tila sinasabi ng compiler, "Okay, okay. Ang iyong code ay naglalaman ng isang grupo ng mga potensyal na pagbubukod, ngunit isasama ko ito. Ngunit babalik tayo sa pag-uusap na ito!" At kapag tumawag ka ng anumang paraan na may hindi nahawakang mga pagbubukod, tinutupad ng compiler ang pangako nito at muling ipinapaalala sa iyo ang tungkol sa mga ito. Sa wakas, pag-uusapan natin ang tungkol sa finallyblock (paumanhin para sa pun). Ito ang huling bahagi ng try-catch-finallyexception sa paghawak ng triumvirate..

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's the finally block!");
   }
}
Sa halimbawang ito, ang code sa loob ng finallyblock ay isasagawa sa parehong mga kaso. Kung ang code sa trybloke ay tumatakbo nang buo nang walang ibinabato na anumang mga pagbubukod, ang finallybloke ay tatakbo sa dulo. Kung ang code sa loob ng tryblock ay naantala ng isang exception at ang program ay tumalon sa catchblock, ang finallyblock ay tatakbo pa rin pagkatapos ng code sa loob ng catchblock. Bakit kailangan ito? Ang pangunahing layunin nito ay magsagawa ng mandatoryong code: code na dapat gawin anuman ang mga pangyayari. Halimbawa, madalas nitong pinapalaya ang ilang mapagkukunang ginagamit ng programa. Sa aming code, nagbubukas kami ng isang stream upang basahin ang impormasyon mula sa file at ipasa ito sa BufferedReaderbagay. Dapat nating isara ang ating mambabasa at ilabas ang mga mapagkukunan. Dapat itong gawin kahit na ano—kapag gumagana ang programa ayon sa nararapat, at kapag naghagis ito ng eksepsiyon. Ang finallybloke ay isang napaka-maginhawang lugar upang gawin ito:

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's the finally block!");
       if (reader != null) {
           reader.close();
       }
   }
}
Ngayon ay sigurado na kami na aalagaan namin ang mga mapagkukunan, anuman ang mangyayari kapag tumatakbo ang programa. :) Hindi lang iyon ang kailangan mong malaman tungkol sa mga exception. Ang paghawak ng error ay isang napakahalagang paksa sa programming. Maraming mga artikulo ang nakatuon dito. Sa susunod na aralin, malalaman natin kung anong mga uri ng mga exception ang mayroon at kung paano gumawa ng sarili mong mga exception. :) See you then!
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION