CodeGym /Java Blog /Random-IT /Eccezioni in Java
John Squirrels
Livello 41
San Francisco

Eccezioni in Java

Pubblicato nel gruppo Random-IT
Ciao! Nella lezione di oggi parleremo delle eccezioni Java. La vita di tutti i giorni è piena di situazioni che non prevediamo. Ad esempio, ti alzi la mattina per andare al lavoro e cerchi il caricabatterie del telefono, ma non lo trovi da nessuna parte. Vai in bagno a fare la doccia solo per scoprire che i tubi sono congelati. Sali in macchina, ma non parte. Un essere umano è in grado di far fronte abbastanza facilmente a tali circostanze impreviste. In questo articolo, cercheremo di capire come i programmi Java li gestiscono.

Cos'è un'eccezione Java?

Nel mondo della programmazione, gli errori e le situazioni impreviste nell'esecuzione di un programma sono chiamate eccezioni. In un programma, possono verificarsi eccezioni a causa di azioni dell'utente non valide, spazio su disco insufficiente o perdita della connessione di rete con il server. Le eccezioni possono anche derivare da errori di programmazione o dall'uso errato di un'API. A differenza degli esseri umani nel mondo reale, un programma deve sapere esattamente come gestire queste situazioni. Per questo, Java ha un meccanismo noto come gestione delle eccezioni.

Qualche parola sulle parole chiave

La gestione delle eccezioni in Java si basa sull'uso delle seguenti parole chiave nel programma:
  • try - definisce un blocco di codice in cui può verificarsi un'eccezione;
  • catch - definisce un blocco di codice in cui vengono gestite le eccezioni;
  • finalmente - definisce un blocco facoltativo di codice che, se presente, viene eseguito indipendentemente dai risultati del blocco try.
Queste parole chiave vengono utilizzate per creare costrutti speciali nel codice: try{}catch , try{}catch{}finally , try{}finally{} .
  • throw - utilizzato per sollevare un'eccezione;
  • throws : utilizzato nella firma del metodo per avvisare che il metodo potrebbe generare un'eccezione.
Un esempio di utilizzo di parole chiave in un programma Java:

// This method reads a string from the keyboard

public String input() throws MyException { // Use throws to warn 
// that the method may throw a MyException
      BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    String s = null;
// We use a try block to wrap code that might create an exception. In this case,
// the compiler tells us that the readLine() method in the 
// BufferedReader class might throw an I/O exception
    try {
        s = reader.readLine();
// We use a catch block to wrap the code that handles an IOException  
    } catch (IOException e) {
        System.out.println(e.getMessage());
// We close the read stream in the finally block
    } finally {
// An exception might occur when we close the stream if, for example, the stream was not open, so we wrap the code in a try block
        try {
            reader.close();
// Handle exceptions when closing the read stream
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    }

    if (s.equals("")) {
// We've decided that an empty string will prevent our program from working properly. For example, we use the result of this method to call the substring(1, 2) method. Accordingly, we have to interrupt the program by using throw to generate our own MyException exception type.
        throw new MyException("The string cannot be empty!");
    }
    return s;
}

Perché abbiamo bisogno di eccezioni?

Diamo un'occhiata a un esempio dal mondo reale. Immagina che un tratto di autostrada abbia un piccolo ponte con portata limitata. Se un'auto più pesante del limite del ponte ci passa sopra, potrebbe crollare. La situazione per l'autista diventerebbe, a dir poco, eccezionale. Per evitare ciò, il dipartimento dei trasporti installa segnali di avvertimento sulla strada prima che qualcosa vada storto. Vedendo il segnale di avvertimento, un conducente confronta il peso del proprio veicolo con il peso massimo per il ponte. Se il veicolo è troppo pesante, il conducente prende una tangenziale. Il dipartimento dei trasporti, in primo luogo, ha consentito ai camionisti di modificare il percorso se necessario, in secondo luogo, ha avvertito i conducenti dei pericoli sulla strada principale e, in terzo luogo, ha avvertito i conducenti che il ponte non deve essere utilizzato in determinate condizioni. Eccezioni in Java - 2La capacità di prevenire e risolvere situazioni eccezionali in un programma, permettendogli di continuare a funzionare, è uno dei motivi per utilizzare le eccezioni in Java. Il meccanismo di eccezione ti consente inoltre di proteggere il tuo codice (API) da un uso improprio convalidando (controllando) qualsiasi input. Ora immagina di essere il dipartimento dei trasporti per un secondo. Innanzitutto, devi conoscere i luoghi in cui gli automobilisti possono aspettarsi problemi. In secondo luogo, è necessario creare e installare segnali di avvertimento. Infine, è necessario fornire deviazioni in caso di problemi sul percorso principale. In Java, il meccanismo delle eccezioni funziona in modo simile. Durante lo sviluppo, utilizziamo un blocco try per creare "barriere di eccezione" attorno a sezioni di codice pericolose, forniamo "percorsi di backup" utilizzando un catch {}block e scriviamo il codice che dovrebbe essere eseguito indipendentemente da ciò che accade in un blocco finally{} . Se non possiamo fornire un "percorso di riserva" o vogliamo dare all'utente il diritto di scegliere, dobbiamo almeno avvertirlo del pericolo. Perché? Immaginate l'indignazione di un automobilista che, senza vedere un solo segnale di avvertimento, raggiunge un ponticello che non può attraversare! Nella programmazione, quando scriviamo le nostre classi e metodi, non possiamo sempre prevedere come potrebbero essere usati da altri sviluppatori. Di conseguenza, non possiamo prevedere il modo corretto al 100% per risolvere una situazione eccezionale. Detto questo, è buona norma avvertire gli altri della possibilità di situazioni eccezionali. Il meccanismo delle eccezioni di Java ci consente di farlo con i tiriparola chiave — essenzialmente una dichiarazione che il comportamento generale del nostro metodo include la generazione di un'eccezione. Pertanto, chiunque utilizzi il metodo sa che dovrebbe scrivere codice per gestire le eccezioni.

Avvisare gli altri di "problemi"

Se non si prevede di gestire le eccezioni nel proprio metodo, ma si desidera avvisare gli altri che potrebbero verificarsi eccezioni, utilizzare la parola chiave throws . Questa parola chiave nella firma del metodo indica che, in determinate condizioni, il metodo può generare un'eccezione. Questo avviso fa parte dell'interfaccia del metodo e consente ai suoi utenti di implementare la propria logica di gestione delle eccezioni. Dopo i lanci, specifichiamo i tipi di eccezioni lanciate. Questi di solito discendono dalla classe Exception di Java . Poiché Java è un linguaggio orientato agli oggetti, tutte le eccezioni sono oggetti in Java. Eccezioni in Java - 3

Gerarchia delle eccezioni

Quando si verifica un errore durante l'esecuzione di un programma, la JVM crea un oggetto del tipo appropriato dalla gerarchia delle eccezioni Java, un insieme di possibili eccezioni che discendono da un antenato comune, la classe Throwable . Possiamo dividere le situazioni di runtime eccezionali in due gruppi:
  1. Situazioni dalle quali il programma non può riprendersi e continuare il normale funzionamento.
  2. Situazioni in cui il recupero è possibile.
Il primo gruppo include situazioni che coinvolgono un'eccezione che discende dalla classe Error . Si tratta di errori che si verificano a causa di un malfunzionamento della JVM, overflow della memoria o errore del sistema. Di solito indicano problemi seri che non possono essere risolti dal software. In Java, la possibilità di tali eccezioni non è verificata dal compilatore, quindi sono note come eccezioni non verificate. Questo gruppo include anche RuntimeExceptions, che sono eccezioni che discendono dall'eccezioneclass e sono generati dalla JVM in fase di esecuzione. Sono spesso causati da errori di programmazione. Anche queste eccezioni non sono controllate (deselezionate) in fase di compilazione, quindi non è necessario scrivere codice per gestirle. Il secondo gruppo include situazioni eccezionali che possono essere previste quando stai scrivendo il programma (e quindi dovresti scrivere codice per gestirle). Tali eccezioni sono chiamate eccezioni verificate. Quando si tratta di eccezioni, la maggior parte del lavoro di uno sviluppatore Java consiste nel gestire tali situazioni.

Creazione di un'eccezione

Quando un programma viene eseguito, le eccezioni vengono generate dalla JVM o manualmente utilizzando un'istruzione throw . Quando ciò accade, viene creato un oggetto eccezione in memoria, il flusso principale del programma viene interrotto e il gestore delle eccezioni della JVM tenta di gestire l'eccezione.

La gestione delle eccezioni

In Java, creiamo blocchi di codice in cui anticipiamo la necessità di gestire le eccezioni utilizzando i costrutti try{}catch , try{}catch{}finally e try{}finally{} . Eccezioni in Java - 4Quando viene generata un'eccezione in un blocco try , la JVM cerca un gestore di eccezioni appropriato nel successivo blocco catch . Se un blocco catch ha il gestore di eccezioni richiesto, il controllo gli passa. In caso contrario, la JVM cerca più in basso nella catena di blocchi catch finché non viene trovato il gestore appropriato. Dopo l'esecuzione di un blocco catch , il controllo viene trasferito al blocco finally opzionale. Se una cattura adattablock non viene trovato, quindi JVM interrompe il programma e visualizza la traccia dello stack (lo stack corrente di chiamate al metodo), dopo aver prima eseguito il blocco finally se esiste. Esempio di gestione delle eccezioni:

public class Print {

     void print(String s) {
        if (s == null) {
            throw new NullPointerException("Exception: s is null!");
        }
        System.out.println("Inside print method: " + s);
    }

    public static void main(String[] args) {
        Print print = new Print();
        List list= Arrays.asList("first step", null, "second step");

        for (String s : list) {
            try {
                print.print(s);
            }
            catch (NullPointerException e) {
                System.out.println(e.getMessage());
                System.out.println("Exception handled. The program will continue");
            }
            finally {
                System.out.println("Inside finally block");
            }
            System.out.println("The program is running...");
            System.out.println("-----------------");
        }

    }
    }
Ecco i risultati del metodo principale :

Inside print method: first step
Inside finally block
The program is running...
-----------------
Exception: s is null!
Exception handled. The program will continue
Inside finally block
The program is running...
-----------------
Inside print method: second step
Inside finally block
The program is running...
-----------------
Infine viene in genere utilizzato per chiudere qualsiasi flusso e liberare qualsiasi risorsa aperta/allocata in un blocco try . Tuttavia, quando si scrive un programma, non è sempre possibile tenere traccia della chiusura di tutte le risorse. Per semplificarci la vita, gli sviluppatori di Java offrono il costrutto try-with-resources , che chiude automaticamente tutte le risorse aperte in un blocco try . Il nostro primo esempio può essere riscritto con try-with-resources :

public String input() throws MyException {
    String s = null;
    try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))){
        s = reader.readLine();
   } catch (IOException e) {
       System.out.println(e.getMessage());
   }
    if (s.equals("")) {
        throw new MyException ("The string cannot be empty!");
    }
    return s;
}
Grazie alle funzionalità Java introdotte nella versione 7, possiamo anche combinare la cattura di eccezioni eterogenee in un unico blocco, rendendo il codice più compatto e leggibile. Esempio:

public String input() {
    String s = null;
    try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) {
        s = reader.readLine();
        if (s.equals("")) {
            throw new MyException("The string cannot be empty!");
        }
    } catch (IOException | MyException e) {
        System.out.println(e.getMessage());
    }
    return s;
}

La linea di fondo

L'utilizzo delle eccezioni in Java ti consente di rendere i tuoi programmi più robusti creando "percorsi di backup", utilizzare i blocchi catch per separare il codice principale dal codice di gestione delle eccezioni e utilizzare i tiri per trasferire la responsabilità della gestione delle eccezioni a chiunque utilizzi il tuo metodo .
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION