Poikkeukset tarkoittavat ajonaikaisia virheitä. Poikkeus voi tapahtua esimerkiksi silloin, kun yritetään avata tiedostoa, jota ei ole olemassa. Javassa on kahdenlaisia poikkeuksia: poikkeukset, joita ei ole pakko käsitellä, ja poikkeukset, jotka on pakko käsitellä.

Jos jokin koodirivi saattaa tuottaa poikkeuksen, sen voi käsitellä laittamalla sen try-catch rakenteen sisään. Syntaksi näyttää tältä:

try {
    // koodi joka saattaa aiheuttaa poikkeuksen
} catch (Exception e) {
    // koodi joka suoritetaan jos try-lohkon sisällä oleva koodi aiheuttaa poikkeuksen
}

Catchin sulkeiden sisälle laitetaan poikkeustyyppi, jonka haluat käsitellä catch-lohkossa. Jos laitat poikkeuksen tyypiksi Exception, niin kaikki mahdolliset poikkeukset käsitellään samalla tavalla, mutta näin ei yleensä kannata tehdä. Sen sijaan laita tyypiksi se tietty poikkeustyyppi, jonka haluat käsitellä.

Esimerkiksi jos haluaisit käyttäjän kirjoittavan jonkin luvun, minkä tallennat int-tyyppiseen muuttujaan, niin tästä voi aiheutua poikkeus, jos käyttäjä kirjoittaakin jotain muuta kuin numeroita. Tässä tapauksessa poikkeuksen tyyppi olisi NumberFormatException. Kirjoitetaan koodi, joka käsittelee tämän poikkeustyypin:

Scanner input = new Scanner(System.in);
try {
    System.out.print("Anna luku: ");
    int luku = Integer.valueOf(input.nextLine());
    System.out.println("Kirjoitit luvun " + luku);
} catch (NumberFormatException e) {
    System.out.println("Kirjoitit jotain muuta kuin numeron!");
}

Avainsana throws

Toinen tapa käsitellä poikkeus on lisätä funktion nimen perään sana throws, ja heitettävän poikkeuksen tyyppi. Tämä siirtää vastuun poikkeuksen käsittelystä kyseisen funktion kutsuneelle funktiolle.

public static void main(String[] args) {   
    try {
        int number = getNumberFromUser();
        System.out.println("You typed in the number " + number);
    } catch (NumberFormatException e) {
        System.out.println("Error! Wrong number format");          
    }
}

public static int getNumberFromUser() throws NumberFormatException {
    Scanner input = new Scanner(System.in);
    System.out.print("Input a number: ");
    int number = Integer.valueOf(input.nextLine());
    return number;
}

Esimerkiksi tässä koodissa funktio getNumberFromUser ei itse käsittele mahdollista poikkeusta, joten se täytyy tehdä main-funktiossa.

Monen eri poikkeuksen käsitteleminen

Monen eri poikkeuksen käsitteleminen on helppoa kirjoittamalla monta catch-lohkoa tähän tyyliin:

try {
    // koodi joka saattaa heittää monta poikkeusta
} catch (PoikkeusTyyppi1 e) {
    // koodi joka käsittelee PoikkeusTyyppi1-tyyppiset poikkeukset
} catch (PoikkeusTyyppi2 e) {
    // koodi joka käsittelee PoikkeusTyyppi2-tyyppiset poikkeukset
}