Navigace

Hlavnφ menu

 

Java a v²jimky - pokroΦilΘ techniky

Cφlem Φlßnku bude nastφnit techniky, kterΘ prßci s v²jimkami usnad≥ujφ a dovolujφ nßm v²jimky efektivn∞ vyu₧φvat. Ukß₧eme si °et∞zenφ v²jimek (exception chaining), rozÜφ°enφ Java API ve verzi 1.4 a standardnφ b∞hovΘ v²jimky Javy.

╪et∞zenφ v²jimek

Pot°eba mechanismu °et∞zenφ v²jimek (exception chaining) vyvstala postupn∞ a jeho podpora se v API Javy objevila ve verzi 1.4. ╪et∞zenφ v²jimek vznikß vlo₧enφm zachycenΘ v²jimky do v²jimky jinΘ. Takto nov∞ vytvo°enß v²jimka se propaguje dßle zcela standardnφm mechanismem. Dφky tomuto p°φstupu nemusφme p°i rozÜφ°enφ k≤du propagovat nov² typ v²jimky. Zva₧me nßsledujφcφ k≤d:

public void doSomethingFishy() throws HighLevelException{
    try{
        ...
        ...
    }catch(LowLevelException e){
        throw new HighLevelException();
    }
}

Tento k≤d ned∞lß nic prostÜφho, ne₧ p°eklad kontrolovanΘ v²jimky na jinou kontrolovanou v²jimku, kterß je definovßna v rßmci metody. Nev²hoda tohoto °eÜenφ je z°ejmß, p°ijdeme o vÜechny d∙le₧itΘ informace, kterΘ v sob∞ nese LowLevelException. Dφky tomu u₧ nemusφ b²t dohledßnφ p°φΦiny vzniku HighLevelException snadnΘ.

Mnohem lepÜφ by bylo p°φΦinu (LowLevelException) uschovat, respektive z°et∞zit do HighLevelException. Dφky tomuto p°φstupu vyhovφme kontraktu metody a zßrove≥ neztratφme d∙le₧itΘ informace o p°φΦin∞ vzniku HighLevelException. Nßsledujφcφ k≤d ilustruje z°et∞zenφ v²jimky:

public void doSomethingFishy() throws HighLevelException{
    try{
        ...
        ...
    }catch(LowLevelException e){
        throw new HighLevelException(e);
    }
}

╪et∞zenφ v²jimek a podpora v API

Jak bylo zmφn∞no na zaΦßtku Φlßnku, Java 1.4 jde tomuto p°φstupu naproti. API se v p°φpad∞ p°edka vÜech v²jimek Throwable rozÜφ°ilo o nßsledujφcφ metody:

  • Throwable(Throwable)
  • Throwable(Throwable, String)
  • getCause()
  • initCause(Throwable)
  • printStackTrace
  • get/setStackTrace()

Jak je vid∞t, rozÜφ°enφ se doΦkaly konstruktory, kterΘ umo₧≥ujφ v²jimku p°φmo z°et∞zit do novΘ v²jimky a p°idat zprßvu v²jimky. Metoda getCause() vracφ z°et∞zenou v²jimku a initCause() naopak dovoluje °et∞zenou v²jimku nastavit.

Rßd bych se jeÜt∞ zmφnil o metod∞ printStackTrace(). Volßnφ PrintStackTrace() zp∙sobφ v²pis stacktracu i v²jimky z°et∞zenΘ. V naÜem p°φpad∞ by volßnφ HighLevelException.printStackTrace zp∙sobilo zßrove≥ volßnφ metody LowLevelException.printStackTrace.

Typick²m p°φkladem pro °et∞zenφ v²jimek je situace, kdy mßm∞ n∞kolik relativn∞ vzdßlen²ch typ∙ v²jimek, kterΘ nem∙₧eme seskupit do objektovΘ hierarchie, jak jsme si naznaΦili v p°edchozφm Φlßnku.

public void configure() throws ConfigurationException{
    try{
        ...
        ...
    }catch(FileNotFoundException e){
        throw new ConfigurationException("KonfiguraΦnφ soubor nenalezen",e);
    }catch(PropertyMissingException e){
        throw new ConfigurationException("Chyb∞jφcφ konfiguraΦnφ atribut",e);
    }catch(InvalidFormatException e){
        throw new ConfigurationException("Neznßm² formßt konfigurace",e);
    }
}

Jak je vid∞t z tohoto p°φkladu, mßme t°i r∙znΘ typy v²jimek. Tyto v²jimky bychom museli deklarovat v kontraktu metody, ale my jsme je z°et∞zili do obecn∞jÜφ v²jimky. V p°φpad∞ zpracovßnφ ConfigurationException znßme p°φΦinu vzniku (z°et∞zenß v²jimka) a mßme popisujφcφ text. Tyto informace minimßln∞ postaΦujφ k dohledßnφ chyby a k rozumnΘ informaci pro u₧ivatele.

U₧iteΦnΘ postupy

Po °et∞zenφ v²jimek se podφvßme na rady, kterΘ jsou obecn∞jÜφho charakteru.

Poskytujte dopl≥ujφcφ informace

Ve v∞tÜin∞ p°φpad∙ se hodφ, pokud v²jimka poskytuje dalÜφ informace, nejen zprßvu, kterou by m∞la obsahovat v₧dy. Tyto informace nßm pomohou k lepÜφmu odhalenφ p°φΦiny a zßrove≥ mohou poslou₧it i u₧ivatel∙m. ╪ekn∞me, ₧e mßme v²jimku, kterß informuje o tom, ₧e osoba nebyla nalezena. Takovß v²jimka by m∞la obsahovat nejen zprßvu o tom, ₧e osoba nebyla nalezena, ale i data, podle kter²ch byla osoba hledßna, nap°φklad rodnΘ Φφslo. Tento p°φpad ilustruje nßsledujφcφ definice v²jimky:

public class OsobaNotFoundException() extends Exception{
    private String rc = null;

    public OsobaNotFoundException(){
        super();
    }

    public OsobaNotFoundException(String message){
        super(message);
    }

    public OsobaNotFoundException(String message, String rc){    
    super(message);
        this.rc = rc;
    }

    public void setRodneCislo(String rc){
        this.rc = rc;
    }

    public void getRodneCislo(){
        return this.rc;
    }
}

Vyu₧φvejte standardnφ v²jimky

API Javy nabφzφ n∞kolik u₧iteΦn²ch b∞hov²ch v²jimek, jejich₧ pou₧itφ je vhodnΘ zvß₧it. Dφky obecnΘ znßmosti jejich v²znamu uΦinφte vßÜ k≤d transparentn∞jÜφm.

  • NullPointerException
  • IllegalStateException
  • UnsupportedOperationException
  • IllegalArgumentException

V²jimku NullPointerException se vyplatφ vyhazovat na t∞ch mφstech, kde pot°ebujeme pracovat s instancφ objektu. P°edstavme si k≤d, kter² odebφrß u₧ivatele ze skupiny u₧ivatel∙ podle osobnφho Φφsla:

Set group = ...

public void removeUser(Integer oscis){
    User u = findUserByOscis(oscis);
    group.remove(u);
}

V tomto p°φpad∞ je vhodnΘ p°ed odebrßnφm u₧ivatele zkontrolovat, jestli nenφ osobnφ Φφslo null:

public void removeUser(Integer oscis){
    if(oscis == null){
        throw new NullPointerException("Osobnφ Φφslo u₧ivatele musφ b²t zadßno.");
    }
    User u = findUserByOscis(oscis);
    group.remove(u);
}

V²jimka IllegalStateException se pou₧φvß, pokud je volßnφ metody neoΦekßvanΘ a objekt je ve nekonzistentnφm stavu pro provedenφ danΘ operace, nap°φklad nenφ inicializovßn.

V²jimku UnsupportedOperationException pou₧ijte v p°φpad∞, ₧e danß operace nenφ podporovßna. M∙₧e se jednat o p°φpad, kdy mßme implementovanΘ obecnΘ rozhranφ a jeho specializovanΘ metody nepot°ebujeme, a proto p°i jejich volßnφ vyhazujeme tuto v²jimku.

V²jimku IllegalArgumentException pou₧ijte v p°φpad∞ neoΦekßvanΘho argumentu, respektive jeho hodnoty. Pokud nap°φklad budete mφt k≤d, kter² nastavuje m∞sφc, a n∞kdo zadß "14", vyho∩te tuto v²jimku.

Dokumentujte jak kontrolovanΘ, tak b∞hovΘ v²jimky

Dokumentacφ v²jimek se nemyslφ nic jinΘho, ne₧ komentß° na ·rovni zdrojovΘho k≤du JavaDoc, ze kterΘho se generuje API dokumentace. Zßkladnφ pravidlo znφ: Dokumentujte p°φΦinu vzniku v²jimky.

/**
 * Odebere u₧ivatele urΦenΘho osobnφm Φφslem.
 * @param oscis osobnφ Φφslo u₧ivatele
 * @throws NullPointerException v p°φpad∞, ₧e je osobnφ Φφslo null
 */
public void removeUser(Integer oscis){
    if(oscis == null){
        throw new NullPointerException("Osobnφ Φφslo u₧ivatele musφ b²t zadßno.");
    }
    User u = findUserByOscis(oscis);
    group.remove(u);
}

Vytvo°te si objektovou hierarchii v²jimek

Pro ka₧d² projekt se sna₧te vytvo°it silnou hierarchii v²jimek. Na zaΦßtku nadefinujte zßkladnφ kontrolovanou a b∞hovou v²jimku, od kter²ch dßle odvozujte ostatnφ v²jimky. Dφky tomuto p°φstupu se mohou v²jimky "bezbolestn∞" propagovat z ni₧Üφch aplikaΦnφch ·rovnφ do vyÜÜφch, bez nutnosti zm∞ny k≤du na vyÜÜφch vrstvßch.

Zßv∞r s pootev°en²mi dvφ°ky

Prßce s v²jimkami, respektive jejich efektivnφ vyu₧itφ, je b∞h na dlouhou tra¥. Cφlem tΘto sΘrie Φlßnk∙ nebylo poskytnout ultimßtnφ °eÜenφ vÜech problΘm∙, kterΘ mohou p°i prßci s v²jimkami vyvstat. Jsou dalÜφ mnohem specifiΦt∞jÜφ tΘmata, o kter²ch stojφ za to p°em²Ület - logovßnφ, lokalizace nebo vizualizace v²jimek, ale o tom snad n∞kdy p°φÜt∞. Doufßm, ₧e vßm tyto Φlßnky pomohly pootev°φt problematiku v²jimek, vyvarovat se Üpatn²ch nßvyk∙ a naopak zφskat obecnou p°edstavu o korektnφch postupech.

Pozn. aut.: Za odbornou a jazykovou korekturu d∞kuji TomßÜi ZßluskΘmu.

Pichlφk, Roman (21. 2. 2005)

Java a v²jimky

V²jimky jsou nedφlnou souΦßstφ platformy Java, poskytujφ pokroΦil² mechanismus °eÜenφ v²jimeΦn²ch situacφ. Ukß₧eme si zßkladnφ koncept, nejΦast∞jÜφ chyby p°i prßci souΦasn∞ s jejich odstran∞nφm, i pokroΦilΘ techniky jako je °et∞zenφ v²jimek. Tato sΘrie Φlßnk∙ ji₧ byla uzav°ena, aΦkoli dalÜφ pokraΦovßnφ nelze vylouΦit.