Izjema (Java)/UrsaSaksida

Iz MaFiRaWiki

GFDL Avtor tega članka je študent/ka UrsaSaksida.

Pripravil/a ga je pri predmetu Računalništvo 2 (FMF PRA).


Kljub temu ste vsi vabljeni k urejanju in popravkom, saj je bistvo wikija ravno v sodelovalnem delu.

Vsebina

Kaj so izjeme?

Izjeme so posebni dogodki, ki se sprožijo ob izvajanju programa, kadar v programu pride do napake. Izvajanje programa se ob tem prekine, kar pa ponavadi ni zaželeno.

Kako izjeme prestrežemo?

Obravnavanja izjem se lahko lotimo na dva načina.

  • V metodi, ki lahko sproži izjemo, v deklaraciji to »povemo« z določilom throws in s tem prenesemo odgovornost naprej.
  • Primer:

    1. public class PrelaganjeOdgovornosti{
    2.  
    3. //odgovornost se preloži na Java virtual machine
    4. public static void main(String[] args) throws Exception{
    5. metodaKiSproziIzjemo();
    6. }
    7.  
    8. //prelozimo odgovornost tja, kjer bo metoda klicana.
    9. public static void metodaKiSproziIzjemo()throws Exception{
    10. String niz = "pomlad";
    11. char znak = niz.charAt(6);//sesti znak v nizu ne obstaja, sprozi se izjema
    12. }
    13. }

    Izpis:

    > java PrelaganjeOdgovornosti
    StringIndexOutOfBounds Exception: String index out of range: 6
      at java.lang.String.charAt(Unknown Source)
      at PrelaganjeOdgovornosti.metodaKiSproziIzjemo(PrelaganjeOdgovornosti.java:9)
      at PrelaganjeOdgovornosti.main(PrelaganjeOdgovornosti.java:4)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
      at java.lang.reflect.Method.invoke(Unknown Source)
    >
    
  • Lahko pa izjeme prestrežemo s konstruktom:
  • try{
      A;
    }
     
    catch(ImeIzjeme i){
      B;
    }

    V konstruktu se zgodi naslednje: Izvede A in če se med izvajanjem A sproži izjema ImeIzjeme, se izjema ujame in izvede se B.
    Primer:

    1. public class TryCatch{
    2. public static void main(String[] args){
    3. try{
    4. String niz = args[0];
    5. }
    6. System.out.println("Pozabili ste podati niz.");
    7. }
    8. }
    9. }

    Izpis:

    > java TryCatch
    Pozabili ste podati niz.
    > java TryCatch niz
    Program se je izvedel brez izjem.
    

    Če pa želimo prestreči več izjem hkrati, pa lahko to storimo s pomočjo zaporednih blokov catch.
    V velikih primerih se lahko zgodi, da bi radi nekatere operacije naredili ne glede na to, ali je prišlo do izjeme ali ne. Blok, s katerim to dosežemo, se imenuje finally. Koda v tem bloku se bo izvršila neodvisno od proženja izjeme.
    Struktura:

    try{
      A;
    }
     
    catch(ImeIzjeme1 i){
      B1;
    }
    catch(ImeIzjeme2 i){
      B2;
    }
    .
    .
    .
    catch(ImeIzjemeN i){
      BN;
    }
    finally{
       C;
    }


    Primer:

    1. import java.io.*;
    2. public class VecIzjem{
    3. public static void main(String[] args) throws Exception{
    4. //poskusamo prebrati dano datoteko
    5. try{
    6. String dat = args[0];
    7. BufferedReader datoteka = new BufferedReader(new FileReader(dat));
    8. while(datoteka.ready()) {
    9. System.out.println(datoteka.readLine());
    10. }
    11. datoteka.close();
    12. }
    13. //dva zaporedna catch stavka za dve razlicni izjemi
    14. //izjema se sprozi, ce ne podamo argumenta
    15. System.out.println("Podaj ustrezni argument!");
    16. }
    17. //izjema se sprozi, kadar podana datoteka ne obstaja
    18. System.out.println("Datoteka ne obstaja.");
    19. }
    20. finally{
    21. System.out.println("Blok se izvrsi vedno.");
    22. }
    23. }
    24. }

    Izpis:

     
    > java VecIzjem neobstojecaDatoteka.txt
    Datoteka ne obstaja.
    Blok se izvrsi vedno.
    > java VecIzjem 
    Podaj ustrezni argument!
    Blok se izvrsi vedno.
    > java VecIzjem C:\datoteka.txt
    prva vrstica datoteke
    druga vrstica datoteke
    tretja vrstica datoteke
    Blok se izvrsi vedno.
    >

    Kako sami sprožimo izjemo?

    Velikokrat se zgodi, da glede na pomen vnesenih podatkov ali dobljenih rezultatov želimo sami sprožiti izjemo. Pri izvajanju programa se v takih primerih seveda ne bi sprožila izjema, saj je tu važen pomen kode, katerega moramo razumeti mi in ga ustrezno prirediti.
    Najpogosteje v takem primeru uporabimo konstruktor Exception(String t) s katerim ustvarimo novo izjemo in jo vržemo s pomočjo throw, ki označuje del, ki sproži izjemo.
    Primer:

    1. public class NovaIzjema{
    2. public static void main(String[] args)throws Exception{
    3. int a = 5;
    4. if(a < 6){
    5. throw new Exception("a je manjši od 6");
    6. }
    7. }
    8. }

    Izpis:

    > java NovaIzjema
    Exception: a je manjši od 6
      at NovaIzjema.main(NovaIzjema.java:5)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
      at java.lang.reflect.Method.invoke(Unknown Source)
    >
    


    Načini izpisa

    V bloku catch lahko izjemo izpišemo na več načinov.

    • Lahko izpišemo svoje sporočilo
    • Uporabimo metodo getMessage(), ki jo razred Exception podeduje iz razreda Throwable. Ta metoda nam vrne podroben opis izjeme.
    • Uporabimo metodo toString(), ki je tudi podedovana iz razreda Throwable in nam vrne kratek opis izjeme.

    Primer:

    1. public class NacinIzpisa{
    2. public static void main(String[] args){
    3. izpisIzjeme();
    4. izpisIzjeme1();
    5. }
    6. public static void izpisIzjeme(){
    7. try{
    8. int t = 1/0;
    9. }
    10. System.out.println("Izpis metode toString(): " + i.toString());
    11. System.out.println("Izpis metode getMessage(): " + i.getMessage());
    12. }
    13. }
    14. public static void izpisIzjeme1(){
    15. try{
    16. String[] tabela = {"ohm"};
    17. String niz = tabela[-1];
    18. }
    19. System.out.println("Indeks je izven mej.");
    20. }
    21. }
    22. }

    Izpis:

    > java NacinIzpisa
    Izpis metode toString(): java.lang.ArithmeticException: / by zero
    Izpis metode getMessage(): / by zero
    Indeks je izven mej.
    >
    

    Nekaj najpogostejših izjem

    • ArrayIndexOutOfBoundsException
      Izjema se sproži, kadar želimo dostopati do neobstoječega indeksa v tabeli.
    • StringIndexOutOfBoundsException
      Izjema se sproži, kadar kličemo neobstoječi indeks v tabeli.
    • ArithmeticException
      Izjema se sproži pri deljenju z nič.
    • IOException
      IOException je splošen razred za nadzor napak, ki ga dodamo v parameter catch. S to izjemo odkrivamo vse napake, ne glede na posamezen podtip napake.
    • NullPointerException
      Izjema se sproži, če kličemo metodo na nedefiniranem objektu null.
      Primer:
      1. public class NullPointerException{
      2. public static int[] tabela;
      3. public static void main(String[] args)throws Exception{
      4. izjema();
      5. }
      6. public static void izjema() throws Exception{
      7. int stevilo = tabela[0];
      8. }
      9. }

      Izpis:

      > java NullPointerException
      NullPointerException: 
        at NullPointerException.izjema(NullPointerException.java:9)
        at NullPointerException.main(NullPointerException.java:5)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
      >
      

    Razred Exception

    Razred Exception je podrazred razreda Throwable, glavnega razreda, ki je nadrazred vsem izjemam in napakam v Javi. Od razreda Throwable podeduje vse pomembnejše metode, kot so getMessage(), getCause() (metoda getCause() nam izpiše vzrok za nastanek izjeme) in toString().

    Glej še

Osebna orodja