Gerarchia delle classi di eccezione
Fa parte della sezione Programmazione orientata agli oggetti del percorso Java di Coddy. Lezione 59 di 87.
Il sistema di gestione delle eccezioni di Java si basa su una gerarchia di classi ben organizzata, che ha come radice la classe Throwable. Comprendere questa gerarchia ti aiuta a intercettare e gestire le eccezioni in modo più efficace.
In cima si trova Throwable, la classe genitore di tutte le eccezioni e gli errori. Ha due sottoclassi dirette:
Throwable
├── Error // Problemi gravi (non intercettarli)
└── Exception // Problemi recuperabili
└── RuntimeException // Eccezioni non controllateErrore rappresenta problemi gravi che le applicazioni non dovrebbero cercare di gestire, come OutOfMemoryError o StackOverflowError. Questi indicano problemi fondamentali della JVM stessa.
Exception è il ramo con cui lavorerai più spesso. Si divide in due categorie: eccezioni verificate (sottoclassi dirette di Exception) ed eccezioni non verificate (sottoclassi di RuntimeException).
// Classi di eccezioni comuni
Exception
├── IOException // Problemi relativi a file e rete
├── SQLException // Problemi relativi al database
└── RuntimeException
├── NullPointerException
├── ArrayIndexOutOfBoundsException
└── IllegalArgumentExceptionPoiché le eccezioni sono classi, seguono le regole dell’ereditarietà. Quando catturi un tipo di eccezione genitore, catturi anche tutti i suoi tipi derivati:
try {
// del codice
} catch (Exception e) {
// Cattura TUTTE le eccezioni (di solito troppo generico)
}try {
// del codice
} catch (RuntimeException e) {
// Intercetta solo le eccezioni di runtime e le relative sottoclassi
}Questa gerarchia ti permette di essere specifico o generico quanto necessario nella gestione degli errori ed è la base per creare eccezioni personalizzate.
Sfida
FacileCostruiamo un analizzatore di eccezioni che mostra come funziona in pratica la gerarchia delle eccezioni di Java! Creerai un sistema che intercetta le eccezioni a diversi livelli di specificità e segnala quale tipo è stato intercettato.
Organizzerai il codice in tre file:
ExceptionThrower.java: crea una classe in grado di generare diversi tipi di eccezioni in base all'input. La classe deve avere tre metodi statici:triggerRuntime(String type)- In base alla stringa type, genera diverse eccezioni runtime:- Se type è
"null", genera unaNullPointerExceptioncon il messaggio"Null value encountered" - Se type è
"index", genera unaArrayIndexOutOfBoundsExceptioncon il messaggio"Invalid index" - Se type è
"argument", genera unaIllegalArgumentExceptioncon il messaggio"Bad argument"
triggerArithmetic()- Genera unaArithmeticExceptioncon il messaggio"Division error"triggerGeneric()- Genera unaIllegalStateExceptioncon il messaggio"Generic runtime error"(la sua gerarchia è Exception > RuntimeException > IllegalStateException)- Se type è
ExceptionAnalyzer.java: crea una classe che intercetta le eccezioni a diversi livelli della gerarchia e identifica quale è stata intercettata. Includi questi metodi statici:analyzeSpecific(String type)- ChiamaExceptionThrower.triggerRuntime(type)all'interno di un blocco try. Usa blocchi catch separati perNullPointerException,ArrayIndexOutOfBoundsExceptioneIllegalArgumentException. Per ciascuna, stampa:Caught specific: [exception class simple name]seguito daMessage: [exception message]analyzeWithParent()- ChiamaExceptionThrower.triggerArithmetic()all'interno di un blocco try. Intercettala usandoRuntimeException(il tipo genitore). Stampa:Caught via parent: RuntimeExceptionseguito daActual type: [exception class simple name]analyzeWithGrandparent()- ChiamaExceptionThrower.triggerGeneric()all'interno di un blocco try. Intercettala usandoException(un livello ancora più alto nella gerarchia). Stampa:Caught via grandparent: Exceptionseguito daActual type: [exception class simple name]Main.java: metti insieme il tuo analizzatore di eccezioni! Riceverai un input: una stringa che indica il tipo di eccezione (ovvero"null","index"oppure"argument").Per prima cosa, stampa
=== Specific Catch ===e chiamaanalyzeSpecificcon il tuo input.Poi stampa una riga vuota,
=== Parent Catch ===e chiamaanalyzeWithParent.Infine, stampa una riga vuota,
=== Grandparent Catch ===e chiamaanalyzeWithGrandparent.
Riceverai un input: il tipo di eccezione da generare ("null", "index" oppure "argument").
Usa e.getClass().getSimpleName() per ottenere il nome della classe dell'eccezione e e.getMessage() per recuperarne il messaggio. Questa sfida mostra come intercettare un tipo di eccezione genitore significhi intercettare anche tutti i suoi tipi derivati: un concetto fondamentale per decidere quanto debba essere specifica la gestione delle eccezioni!
Provalo tu
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String type = scanner.nextLine();
// TODO: Stampa "=== Specific Catch ===" e chiama ExceptionAnalyzer.analyzeSpecific(type)
// TODO: Stampa una riga vuota, poi "=== Parent Catch ===", quindi chiama ExceptionAnalyzer.analyzeWithParent()
// TODO: Stampa una riga vuota, poi "=== Grandparent Catch ===", quindi chiama ExceptionAnalyzer.analyzeWithGrandparent()
}
}
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Programmazione orientata agli oggetti
1Fondamenti della programmazione a oggetti
File esterniIntroduzione alla programmazione a oggettiClassi e oggettiLa parola chiave thisMetodiCampi (attributi)Metodo costruttoreSovraccarico dei costruttoriRipasso - Calcolatrice semplice4Ereditarietà
Ereditarietà di base (extends)La parola chiave superSovrascrittura dei metodi (@Override)Concatenamento dei costruttoriLa classe ObjectEreditarietà singola e multilivelloPerché non esiste l'ereditarietà multipla delle classiRiepilogo: gerarchia dei dipendenti7Metodi speciali e classe Object
Metodo toString()equals() e hashCode()Metodo clone()compareTo() e ComparableInterfaccia ComparatorRiepilogo - Ordinamento personalizzato10Gestione delle eccezioni in OOP
Gerarchia delle classi di eccezioneEccezioni personalizzateEccezioni controllate e non controllatePattern try-with-resourcesRiepilogo - Utente validato2Modificatori di accesso e incapsulamento
Panoramica dei livelli di accessoMetodi getter e setterNascondimento delle informazioniLa parola chiave finalRiepilogo - Gestore di conti bancari5Polimorfismo
Nozioni di base sull'overloading dei metodiOverride dei metodi (a runtime)Upcasting e downcastingL'operatore instanceofClassi e metodi astrattiRiepilogo - Calcolatore di forme8Concetti avanzati di OOP
Composizione vs ereditarietàAggregazione vs composizioneClassi interne, annidate e anonimeEnum e metodi degli EnumRecord (Java 16+)Classi sealed (Java 17+)11Modelli di progettazione Parte 1
Introduzione ai modelli di progettazionePattern SingletonPattern FactoryPattern BuilderPattern ObserverPattern Strategy3Proprietà di classe e membri statici
Variabili di istanza e staticheMetodi staticiBlocchi staticiCostanti (static final)Riepilogo - Contatore e utility6Interfacce e classi astratte
Introduzione alle interfacceImplementazione delle interfacceImplementazione di più interfacceMetodi default e static nelle interfacceClassi astratte e interfacce a confrontoInterfacce funzionaliRiepilogo: sistema di pagamento9Tipi generici
Introduzione ai tipi genericiClassi genericheMetodi genericiParametri di tipo con limitiCaratteri jolly (?, extends, super)Riepilogo - Contenitore generico12Modelli di progettazione – Parte 2
Pattern CommandPattern AdapterPattern DecoratorPattern Template MethodPattern StatePattern CompositePattern IteratorEsercitati da solo: Compilatore Java online