JavaRush /Java Blog /Random-IT /Eccezioni in Java (Eccezione Java)

Eccezioni in Java (Eccezione Java)

Pubblicato nel gruppo Random-IT
Nella vita di tutti i giorni a volte si verificano situazioni che non avevamo previsto. Ad esempio, ti alzi la mattina per andare al lavoro, cerchi un caricabatterie per il tuo telefono, ma non ce n'è uno. Vai in bagno per lavarti la faccia: l'acqua è stata chiusa. Sono entrato in macchina e non partiva. Ma una persona è in grado di affrontare tali situazioni impreviste abbastanza facilmente. Cercheremo di capire come i programmi Java li gestiscono in questo articolo.

Cosa sono le eccezioni Java

Nel mondo della programmazione, il verificarsi di errori e situazioni impreviste durante l'esecuzione del programma viene chiamato eccezione. In un programma, possono verificarsi eccezioni a seguito di azioni errate dell'utente, mancanza di una risorsa necessaria sul disco o perdita di connessione al server tramite la rete. Eccezioni durante l'esecuzione del programma possono essere causate anche da errori di programmazione o da un errato utilizzo delle API. A differenza del nostro mondo, il programma deve sapere chiaramente cosa fare in una situazione del genere. Java fornisce un meccanismo di eccezione a questo scopo.

Brevemente sulle parole chiave prova, cattura, infine, lancia

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 il blocco di codice in cui viene gestita l'eccezione;
  • infine – definisce un blocco di codice facoltativo, ma se presente, viene comunque eseguito, indipendentemente dai risultati del blocco try.
Queste parole chiave vengono utilizzate per creare speciali costrutti di elaborazione nel codice del programma: try{}catch, try{}catch{}finally, try{}finally{}.
  • lanciare – utilizzato per sollevare un'eccezione;
  • lanci: utilizzato nelle firme dei metodi per avvisare che il metodo potrebbe generare un'eccezione.
Un esempio di utilizzo delle parole chiave in un programma Java:
//method reads a string from the keyboard

public String input() throws MyException {//warn with throws,
// that the method can throw MyException
      BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    String s = null;
// in the try block we enclose the code in which an exception can occur, in this
// if the compiler tells us that the readLine() method of the class
// BufferedReader may throw an I/O exception
    try {
        s = reader.readLine();
// in the catch block we enclose the code for handling the IOException exception
    } catch (IOException e) {
        System.out.println(e.getMessage());
// close the read stream in the finally block
    } finally {
// when closing the stream, an exception is also possible, for example, if it was not opened, so we “wrap” the code in a try block
        try {
            reader.close();
// write exception handling when closing the read stream
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    }

    if (s.equals("")) {
// we decided that an empty string could disrupt the work of our program in the future, for example, on the result of this method, we need to call the substring(1,2) method, so we are forced to interrupt the program execution with the generation of our exception type MyException using throw
        throw new MyException("String can not be empty!");
    }
    return s;
}

Perché abbiamo bisogno di un meccanismo di eccezione?

Diamo un'occhiata a un esempio del mondo reale. Immagina che ci sia un tratto di un'autostrada con un ponte di emergenza con capacità di carico limitata. Se un veicolo con una massa superiore alla capacità di carico del ponte lo attraversa, potrebbe crollare e la situazione per il conducente potrebbe diventare, per usare un eufemismo, eccezionale. Per evitare che ciò accada, il servizio stradale installa in anticipo segnali di avvertimento sulla strada. Il conducente dell'auto, guardando il segnale di pericolo, confronterà il peso della sua vettura con quello consentito per la circolazione sul ponte. Se lo supera, prenderà una deviazione. Grazie agli interventi del servizio stradale, i camionisti hanno avuto, da un lato, la possibilità di modificare anticipatamente il proprio percorso, dall'altro, sono stati avvertiti del pericolo sulla strada principale e, infine, dell'impossibilità di utilizzare il ponte in determinate condizioni.
Eccezioni in Java - 2
La capacità di prevenire e risolvere un'eccezione in un programma in modo che possa continuare è uno dei motivi per utilizzare le eccezioni in Java. Il meccanismo di eccezione consente inoltre di proteggere il codice scritto (interfaccia di programmazione) da un uso improprio da parte dell'utente convalidando (controllando) i dati in ingresso. Ora, per un secondo, saremo la polizia stradale. Innanzitutto, dovresti conoscere i luoghi in cui gli automobilisti possono finire nei guai. In secondo luogo, è necessario preparare e installare i segnali di avvertimento. Infine, è necessario prevedere percorsi di deviazione in caso di pericolo sul percorso principale. In Java, il meccanismo delle eccezioni funziona in modo simile. Nella fase di sviluppo del programma, "proteggiamo" sezioni pericolose di codice dalle eccezioni utilizzando il blocco try{}, forniamo percorsi di "backup" utilizzando il blocco catch{} e nel blocco last{} scriviamo il codice che viene eseguito nel programma per qualsiasi risultato. Nei casi in cui non possiamo prevedere una “via di emergenza” o vogliamo lasciare deliberatamente la scelta all’utente, dobbiamo almeno avvisarlo del pericolo. Perché? Immaginate l'indignazione di un automobilista che raggiungerà un ponte di emergenza non transitabile senza incontrare un solo segnale di pericolo lungo il percorso! Nella programmazione, quando scriviamo le nostre classi e metodi, non possiamo sempre prevedere il contesto del loro utilizzo da parte di altri sviluppatori nei loro programmi, quindi non possiamo prevedere il percorso corretto al 100% per risolvere la situazione di eccezione. Allo stesso tempo, è buona norma avvisare gli utenti del nostro codice della possibilità di un’eccezione. Il meccanismo di eccezione di Java ci consente di farlo utilizzando i lanci, dichiarando essenzialmente il comportamento generale del nostro metodo per lanciare un'eccezione, lasciando così all'utente del metodo la scrittura del codice per gestire l'eccezione in Java.

Avviso di "guai"

Quando non prevedi di gestire un'eccezione nel tuo metodo, ma desideri avvisare gli utenti del metodo su possibili situazioni di eccezione, utilizza la parola chiave Throws. Questa parola chiave nella firma di un metodo significa che in determinate condizioni il metodo potrebbe generare un'eccezione. Questo avviso fa parte dell'interfaccia del metodo e concede all'utente il diritto di personalizzare l'implementazione del gestore delle eccezioni. Dopo i lanci indichiamo il tipo di eccezione lanciata. Questi sono solitamente discendenti della classe Java Exception . Poiché Java è un linguaggio orientato agli oggetti, tutte le eccezioni in Java sono oggetti.
Eccezioni in Java - 3

Gerarchia delle eccezioni Java

Quando si verifica un errore durante l'esecuzione del programma, il runtime JVM crea un oggetto del tipo richiesto dalla gerarchia delle eccezioni Java - l'insieme di possibili eccezioni ereditate da un "antenato" comune - la classe Throwable. Le situazioni eccezionali che si verificano in un programma possono essere divise in due gruppi:
  1. Situazioni in cui è impossibile ripristinare il normale funzionamento del programma
  2. Il recupero è possibile.
Il primo gruppo include situazioni in cui si verificano eccezioni ereditate dalla classe Error . Si tratta di errori che si verificano durante l'esecuzione del programma a seguito di un errore JVM, overflow della memoria o arresto anomalo del sistema. Di solito indicano problemi seri che non possono essere risolti utilizzando il software. Questo tipo di eccezione in Java è classificata come non controllata in fase di compilazione. Questo gruppo include anche RuntimeException - eccezioni, eredi della classe Exception , generate dalla JVM durante l'esecuzione del programma. Spesso sono causati da errori di programmazione. Queste eccezioni vengono deselezionate anche in fase di compilazione, quindi non è necessario scrivere codice per gestirle. Nel secondo gruppo rientrano le situazioni eccezionali previste in fase di scrittura del programma e per le quali è necessario scrivere il codice di elaborazione. Tali eccezioni vengono controllate. La maggior parte del lavoro di uno sviluppatore Java quando ha a che fare con le eccezioni è gestire tali situazioni.

Creazione di un'eccezione

Durante l'esecuzione del programma, viene generata un'eccezione dalla JVM o manualmente utilizzando l' istruzione Throw . Ciò crea un oggetto eccezione in memoria e interrompe l'esecuzione del codice del programma principale mentre il gestore delle eccezioni JVM tenta di trovare un modo per gestire l'eccezione.

La gestione delle eccezioni

La creazione di blocchi di codice per i quali forniamo la gestione delle eccezioni in Java viene eseguita nel programma utilizzando i costrutti try{}catch, try{}catch{}finally, try{}finally{}.
Eccezioni in Java - 4
Quando viene sollevata un'eccezione in un blocco try, il gestore dell'eccezione viene cercato nel blocco catch successivo. Se il catch contiene un gestore per questo tipo di eccezione, il controllo gli passa. In caso contrario, la JVM cerca un gestore per quel tipo di eccezione nella catena di chiamate al metodo finché non viene trovato un catch adatto. Dopo l'esecuzione del blocco catch, il controllo viene passato a un blocco last facoltativo . Se non viene trovato un blocco catch adatto, la JVM interrompe l'esecuzione del programma e visualizza uno stack di chiamate al metodo - stack trace , dopo aver precedentemente eseguito il codice del blocco finale, se presente. 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 method print: " + 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 was processed. Program continues");
            }
            finally {
                System.out.println("Inside bloсk finally");
            }
            System.out.println("Go program....");
            System.out.println("-----------------");
        }

    }
    }
I risultati del metodo principale :
Inside method print: first step
Inside bloсk finally
Go program....
-----------------
Exception: s is null!
Exception was processed. Program continues
Inside bloсk finally
Go program....
-----------------
Inside method print: second step
Inside bloсk finally
Go program....
-----------------
Il blocco finallyviene solitamente utilizzato per chiudere i flussi aperti nel blocco try o per liberare risorse. Tuttavia, quando si scrive un programma, non è sempre possibile tenere traccia della chiusura di tutte le risorse. Per semplificarci la vita, gli sviluppatori Java ci hanno offerto un costrutto try-with-resourcesche chiude automaticamente le risorse aperte in un blocco try. Il nostro primo esempio può essere riscritto in questo modo 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 ("String can not be empty!");
    }
    return s;
}
Grazie alle funzionalità di Java, a partire dalla versione 7, possiamo anche combinare la cattura di diversi tipi di eccezioni in un unico blocco, rendendo il codice più compatto e leggibile. Per 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("String can not be empty!");
        }
    } catch (IOException | MyException e) {
        System.out.println(e.getMessage());
    }
    return s;
}

Risultati

L'utilizzo delle eccezioni in Java ci consente di aumentare la tolleranza agli errori del programma attraverso l'uso di percorsi di "backup", separare la logica del codice principale dal codice di gestione delle eccezioni attraverso l'uso di blocchi catch e ci dà anche l'opportunità di delegare gestione delle eccezioni per l'utente del nostro codice utilizzando i lanci.
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION