1. Mga uri ng eksepsiyon

Mga uri ng pagbubukod

Ang lahat ng mga pagbubukod ay nahahati sa 4 na uri, na talagang mga klase na nagmamana sa isa't isa.

Throwableklase

Ang batayang klase para sa lahat ng mga pagbubukod ay ang Throwableklase. Ang Throwableklase ay naglalaman ng code na nagsusulat ng kasalukuyang stack ng tawag (stack trace ng kasalukuyang pamamaraan) sa isang array. Malalaman natin kung ano ang stack trace sa ibang pagkakataon.

Ang throw operator ay maaari lamang tumanggap ng isang bagay na nagmula sa Throwableklase. At bagama't maaari kang magsulat ng code tulad ng throw new Throwable();, walang sinuman ang karaniwang gumagawa nito. Ang pangunahing layunin ng Throwableklase ay magkaroon ng isang solong magulang na klase para sa lahat ng mga pagbubukod.

Errorklase

Ang susunod na klase ng exception ay ang Errorklase, na direktang nagmamana sa Throwableklase. Ang makina ng Java ay lumilikha ng mga bagay ng Errorklase (at ang mga inapo nito) kapag may naganap na mga seryosong problema . Halimbawa, isang malfunction ng hardware, hindi sapat na memorya, atbp.

Karaniwan, bilang isang programmer, wala kang magagawa sa isang sitwasyon kung saan ang ganitong error (ang uri kung saan Errordapat itapon) ay naganap sa programa: ang mga error na ito ay masyadong seryoso. Ang magagawa mo lang ay abisuhan ang user na nag-crash ang program at/o isulat ang lahat ng kilalang impormasyon tungkol sa error sa log ng program.

Exceptionklase

Ang Exceptionat RuntimeExceptionmga klase ay para sa mga karaniwang error na nangyayari sa pagpapatakbo ng maraming pamamaraan. Ang layunin ng bawat itinapon na pagbubukod ay mahuli ng isang catchbloke na nakakaalam kung paano ito maayos na pangasiwaan.

Kapag hindi makumpleto ng isang paraan ang gawain nito sa ilang kadahilanan, dapat nitong ipaalam kaagad ang paraan ng pagtawag sa pamamagitan ng paglalagay ng pagbubukod sa naaangkop na uri.

Sa madaling salita, kung ang isang variable ay katumbas ng null, ang pamamaraan ay magtapon ng isang NullPointerException. Kung ang mga maling argumento ay naipasa sa pamamaraan, ito ay magtapon ng isang InvalidArgumentException. Kung ang pamamaraan ay hindi sinasadyang nahati sa zero, ito ay magtapon ng isang ArithmeticException.

RuntimeExceptionklase

RuntimeExceptionsay isang subset ng Exceptions. Maaari pa nga nating sabihin na iyon RuntimeExceptionay isang magaan na bersyon ng mga ordinaryong eksepsiyon ( Exception) — mas kaunting mga kinakailangan at paghihigpit ang ipinapataw sa mga naturang eksepsiyon

Malalaman mo ang pagkakaiba sa pagitan ng Exceptionat RuntimeExceptionmamaya.


2. Throws: nasuri ang mga pagbubukod

Throws: may check na mga exception

Ang lahat ng Java exception ay nahahati sa 2 kategorya: may check at uncheck .

Lahat ng mga pagbubukod na nagmamana ng RuntimeExceptiono Erroritinuturing na mga hindi nasuri na mga pagbubukod . Lahat ng iba ay nasuri na mga eksepsiyon .

Mahalaga!

Dalawampung taon pagkatapos ng mga naka-check na eksepsiyon ay ipinakilala, halos lahat ng Java programmer ay nag-iisip na ito ay isang bug. Sa mga sikat na modernong framework, 95% ng lahat ng mga exception ay walang check. Ang wikang C#, na halos eksaktong kinopya ang Java, ay hindi nagdagdag ng mga naka-check na exception .

Ano ang pangunahing pagkakaiba sa pagitan ng mga naka-check at hindi na-check na mga exception?

May mga karagdagang kinakailangan na ipinapataw sa mga naka-check na exception. Sa halos pagsasalita, ang mga ito ay ito:

Kinakailangan 1

Kung ang isang paraan ay naghagis ng may check na exception , dapat itong ipahiwatig ang uri ng exception sa lagda nito . Sa ganoong paraan, alam ng bawat paraan na tumatawag dito na ang "makabuluhang pagbubukod" na ito ay maaaring mangyari dito.

Ipahiwatig ang mga may check na exception pagkatapos ng mga parameter ng pamamaraan pagkatapos ng throwskeyword (huwag gamitin ang throwkeyword nang hindi sinasadya). Mukhang ganito:

type method (parameters) throws exception

Halimbawa:

sinuri ang pagbubukod walang check na exception
public void calculate(int n) throws Exception
{
   if (n == 0)
      throw new Exception("n is null!");
}
public void calculate(n)
{
   if (n == 0)
      throw new RuntimeException("n is null!");
}

Sa halimbawa sa kanan, ang aming code ay naghagis ng hindi naka-check na exception — walang karagdagang aksyon ang kinakailangan. Sa halimbawa sa kaliwa, ang pamamaraan ay nagtatapon ng may check na exception, kaya ang throwskeyword ay idinagdag sa method signature kasama ang uri ng exception.

Kung inaasahan ng isang paraan na maghagis ng maramihang mga naka-check na exception, lahat ng mga ito ay dapat na tukuyin pagkatapos ng throwskeyword, na pinaghihiwalay ng mga kuwit. Ang order ay hindi mahalaga. Halimbawa:

public void calculate(int n) throws Exception, IOException
{
   if (n == 0)
      throw new Exception("n is null!");
   if (n == 1)
      throw new IOException("n is 1");
}

Kinakailangan 2

Kung tatawagan mo ang isang paraan na nagsuri ng mga pagbubukod sa lagda nito, hindi mo maaaring balewalain ang katotohanan na itinapon nito ang mga ito.

Dapat mong mahuli ang lahat ng gayong mga pagbubukod sa pamamagitan ng pagdaragdag catchng mga bloke para sa bawat isa, o sa pamamagitan ng pagdaragdag ng mga ito sa isang throwssugnay para sa iyong pamamaraan.

Para bang sinasabi natin, " Napakahalaga ng mga eksepsiyon na ito kaya dapat nating hulihin ang mga ito. At kung hindi natin alam kung paano haharapin ang mga ito, kung gayon ang sinumang maaaring tumawag sa ating pamamaraan ay dapat na maabisuhan na ang gayong mga eksepsiyon ay maaaring mangyari dito.

Halimbawa:

Isipin na nagsusulat kami ng isang paraan upang lumikha ng isang mundo na pinaninirahan ng mga tao. Ang paunang bilang ng mga tao ay ipinasa bilang isang argumento. Kaya kailangan nating magdagdag ng mga pagbubukod kung napakakaunting tao.

Paglikha ng Earth Tandaan
public void createWorld(int n) throws EmptyWorldException, LonelyWorldException
{
   if (n == 0)
      throw new EmptyWorldException("There are no people!");
   if (n == 1)
      throw new LonelyWorldException ("There aren't enough people!");
   System.out.println("A wonderful world was created. Population: " + n);
}
Ang pamamaraan ay potensyal na magtapon ng dalawang naka-check na mga pagbubukod:

  • EmptyWorldException
  • LonelyWorldException

Ang tawag sa pamamaraang ito ay maaaring pangasiwaan sa 3 paraan:

1. Huwag mahuli ang anumang mga pagbubukod

Ito ay kadalasang ginagawa kapag ang pamamaraan ay hindi alam kung paano maayos na pangasiwaan ang sitwasyon.

Code Tandaan
public void createPopulatedWorld(int population)
throws EmptyWorldException, LonelyWorldException
{
   createWorld(population);
}
Ang paraan ng pagtawag ay hindi nakakakuha ng mga pagbubukod at dapat ipaalam sa iba ang tungkol sa mga ito: idinaragdag nito ang mga ito sa sarili nitong throwssugnay

2. Mahuli ang ilan sa mga pagbubukod

Hinahawakan namin ang mga pagkakamali na kaya naming hawakan. Pero yung hindi natin naiintindihan, ibinabato natin sa calling method. Para magawa ito, kailangan nating idagdag ang kanilang pangalan sa throws clause:

Code Tandaan
public void createNonEmptyWorld(int population)
throws EmptyWorldException
{
   try
   {
      createWorld(population);
   }
   catch (LonelyWorldException e)
   {
      e.printStackTrace();
   }
}
Ang tumatawag ay nakakakuha lamang ng isang naka-check na exception — LonelyWorldException. Ang iba pang pagbubukod ay dapat idagdag sa lagda nito, na nagsasaad nito pagkatapos ng throwskeyword

3. Mahuli ang lahat ng mga pagbubukod

Kung ang pamamaraan ay hindi nagtatapon ng mga pagbubukod sa paraan ng pagtawag, kung gayon ang paraan ng pagtawag ay palaging tiwala na ang lahat ay gumana nang maayos. At hindi ito makakagawa ng anumang aksyon upang ayusin ang isang pambihirang sitwasyon.

Code Tandaan
public void createAnyWorld(int population)
{
   try
   {
      createWorld(population);
   }
   catch (LonelyWorldException e)
   {
      e.printStackTrace();
   }
   catch (EmptyWorldException e)
   {
      e.printStackTrace();
   }
}
Ang lahat ng mga pagbubukod ay nakuha sa pamamaraang ito. Magtitiwala ang tumatawag na naging maayos ang lahat.


3. Pagbubukod sa pagbabalot

Ang mga nasuri na eksepsiyon ay tila cool sa teorya, ngunit naging isang malaking pagkabigo sa pagsasanay.

Ipagpalagay na mayroon kang isang napakapopular na pamamaraan sa iyong proyekto. Tinatawag ito mula sa daan-daang lugar sa iyong programa. At nagpasya kang magdagdag ng bagong may check na exception dito. At maaaring ang naka-check na exception na ito ay talagang mahalaga at napakaespesyal na ang main()paraan lamang ang nakakaalam kung ano ang gagawin kung ito ay nahuli.

Nangangahulugan iyon na kailangan mong idagdag ang may check na exception sa throwssugnay ng bawat paraan na tumatawag sa iyong napakasikat na paraan . Pati na rin sa throwssugnay ng lahat ng mga pamamaraan na tumatawag sa mga pamamaraang iyon. At sa mga pamamaraan na tumatawag sa mga pamamaraang iyon.

Bilang resulta, ang throwsmga sugnay ng kalahati ng mga pamamaraan sa proyekto ay nakakakuha ng bagong naka-check na exception. At siyempre ang iyong proyekto ay sakop ng mga pagsubok, at ngayon ang mga pagsubok ay hindi nag-compile. At ngayon kailangan mo ring i-edit ang mga throws clause sa iyong mga pagsubok.

At pagkatapos ang lahat ng iyong code (lahat ng mga pagbabago sa daan-daang mga file) ay kailangang suriin ng iba pang mga programmer. At sa puntong ito tinatanong natin ang ating sarili kung bakit gumawa tayo ng napakaraming madugong pagbabago sa proyekto? (mga?) araw ng trabaho, at mga sirang pagsubok — lahat para sa kapakanan ng pagdaragdag ng isang may check na exception?

At siyempre, may mga problema pa rin na may kaugnayan sa mana at overriding ng pamamaraan. Ang mga problemang nagmumula sa mga nasuri na eksepsiyon ay mas malaki kaysa sa benepisyo. Ang bottomline ay kakaunti na ang nagmamahal sa kanila ngayon at kakaunti ang gumagamit nito.

Gayunpaman, mayroon pa ring maraming code (kabilang ang karaniwang Java library code) na naglalaman ng mga naka-check na exception na ito. Ano ang dapat gawin sa kanila? Hindi natin sila maaaring balewalain, at hindi natin alam kung paano haharapin ang mga ito.

Iminungkahi ng mga programmer ng Java na i-wrap ang mga naka-check na exception sa RuntimeException. Sa madaling salita, hulihin ang lahat ng may check na mga exception at pagkatapos ay lumikha ng mga hindi naka-check na mga exception (halimbawa, RuntimeException) at itapon ang mga ito sa halip. Ang paggawa nito ay mukhang ganito:

try
{
   // Code where a checked exception might occur
}
catch(Exception exp)
{
   throw new RuntimeException(exp);
}

Ito ay hindi isang napakagandang solusyon, ngunit walang kriminal dito: ang pagbubukod ay pinalamanan lamang sa loob ng isang RuntimeException.

Kung ninanais, madali mong makuha ito mula doon. Halimbawa:

Code Tandaan
try
{
   // Code where we wrap the checked exception
   // in a RuntimeException
}
catch(RuntimeException e)
{
   Throwable cause = e.getCause();
   if (cause instanceof Exception)
   {
      Exception exp = (Exception) cause;
      // Exception handling code goes here
   }
}







Kunin ang pagbubukod na naka-imbak sa loob ng RuntimeExceptionbagay. Ang causevariable ay maaaring null

Tukuyin ang uri nito at i-convert ito sa isang naka-check na uri ng pagbubukod.


4. Pagkuha ng maraming exception

Ayaw talaga ng mga programmer na duplicate ang code. Nakabuo pa sila ng kaukulang prinsipyo ng pag-unlad: Huwag Ulitin ang Iyong Sarili (DRY) . Ngunit kapag humahawak ng mga pagbubukod, may mga madalas na pagkakataon na ang isang trybloke ay sinusundan ng ilang catchmga bloke na may parehong code.

O maaaring mayroong 3 catchbloke na may parehong code at isa pang 2 catchbloke na may iba pang magkaparehong code. Ito ay isang karaniwang sitwasyon kapag ang iyong proyekto ay humahawak ng mga pagbubukod nang responsable.

Simula sa bersyon 7, sa wikang Java ay nagdagdag ng kakayahang tumukoy ng maraming uri ng mga pagbubukod sa isang catchbloke. Mukhang ganito:

try
{
   // Code where an exception might occur
}
catch (ExceptionType1 | ExceptionType2 | ExceptionType3 name)
{
   // Exception handling code
}

Maaari kang magkaroon ng maraming catchmga bloke hangga't gusto mo. Gayunpaman, hindi maaaring tukuyin ng isang catchbloke ang mga pagbubukod na nagmamana sa isa't isa. Sa madaling salita, hindi ka maaaring sumulat ng catch ( Exception| RuntimeExceptione), dahil ang RuntimeExceptionklase ay namamana Exception.



5. Mga custom na exception

Maaari kang lumikha ng sarili mong klase ng pagbubukod anumang oras. Gumawa ka lang ng klase na nagmamana ng RuntimeExceptionklase. Magiging ganito ang hitsura nito:

class ClassName extends RuntimeException
{
}

Tatalakayin namin ang mga detalye habang natututo ka ng OOP, inheritance, constructor, at paraan ng overriding.

Gayunpaman, kahit na mayroon ka lamang isang simpleng klase na tulad nito (ganap na walang code), maaari ka pa ring magtapon ng mga pagbubukod batay dito:

Code Tandaan
class Solution
{
   public static void main(String[] args)
   {
      throw new MyException();
   }
}

class MyException extends RuntimeException
{
}




Magtapon ng walang check MyException .

Sa Java Multithreading quest, magsasagawa kami ng malalim na pagsisid sa pagtatrabaho gamit ang sarili naming mga custom na exception.