Java fornisce un approccio robusto e orientato agli oggetti per gestire scenari di eccezione noti come Gestione delle eccezioni in Java. Tempo fa ho scritto un lungo post sulla Gestione delle eccezioni in Java e oggi sto elencando alcune importanti Domande e Risposte sulle Eccezioni in Java per aiutarti nei colloqui.
- Cos’è un’eccezione in Java?
- Quali sono le parole chiave per la gestione delle eccezioni in Java?
- Spiega l’Gerarchia delle Eccezioni in Java?
- Quali sono i metodi importanti della classe Eccezione di Java?
- Spiega la funzionalità ARM di Java 7 e il blocco multi-catch?
- Qual è la differenza tra Eccezioni Verificate e non Verificate in Java?
- Qual è la differenza tra le parole chiave throw e throws in Java?
- Come scrivere eccezioni personalizzate in Java?
- Cos’è OutOfMemoryError in Java?
- Quali sono i diversi scenari che causano “Eccezione nel thread principale”?
- Qual è la differenza tra final, finally e finalize in Java?
- Cosa succede quando un’eccezione viene lanciata dal metodo principale?
- Possiamo avere un blocco catch vuoto?
- Fornire alcuni suggerimenti per la gestione delle eccezioni in Java?
- Qual è il problema con i seguenti programmi e come possiamo risolverlo?
1. Cos’è un’eccezione in Java?
Un’eccezione è un evento di errore che può verificarsi durante l’esecuzione di un programma e interrompe il suo flusso normale. L’eccezione può derivare da diverse situazioni come dati errati inseriti dall’utente, guasti hardware, fallimento della connessione di rete, ecc. Ogni volta che si verifica un errore durante l’esecuzione di una dichiarazione Java, viene creato un oggetto eccezione e poi JRE cerca di trovare un gestore eccezioni per gestire l’eccezione. Se viene trovato un gestore eccezioni appropriato, l’oggetto eccezione viene passato al codice del gestore per elaborare l’eccezione, noto come catturare l’eccezione. Se non viene trovato alcun gestore, l’applicazione genera l’eccezione all’ambiente di runtime e JRE termina il programma. Il framework di gestione delle eccezioni in Java viene utilizzato solo per gestire gli errori di runtime, gli errori di compilazione non sono gestiti dal framework di gestione delle eccezioni.
2. Quali sono le parole chiave di gestione delle eccezioni in Java?
Ci sono quattro parole chiave utilizzate nella gestione delle eccezioni in Java.
- throw: A volte vogliamo esplicitamente creare un oggetto eccezione e poi lanciarlo per interrompere l’elaborazione normale del programma. La parola chiave throw è utilizzata per lanciare eccezioni al runtime per gestirle.
- throws: Quando stiamo lanciando un’eccezione controllata in un metodo e non la stiamo gestendo, allora dobbiamo usare la parola chiave throws nella firma del metodo per far sapere al programma chiamante le eccezioni che potrebbero essere lanciate dal metodo. Il metodo chiamante potrebbe gestire queste eccezioni o propagarle al suo metodo chiamante utilizzando la parola chiave
throws
. Possiamo fornire più eccezioni nella clausola throws e può essere utilizzata anche con il metodo main(). - try-catch: Utilizziamo il blocco try-catch per la gestione delle eccezioni nel nostro codice. try è l’inizio del blocco e catch è alla fine del blocco try per gestire le eccezioni. Possiamo avere più blocchi catch con un try e i blocchi try-catch possono essere anche nidificati. Il blocco catch richiede un parametro che dovrebbe essere di tipo Exception.
- Infine: Il blocco finally è facoltativo e può essere utilizzato solo con un blocco try-catch. Poiché l’eccezione interrompe il processo di esecuzione, potremmo avere alcune risorse aperte che non verranno chiuse, quindi possiamo usare il blocco finally. Il blocco finally viene eseguito sempre, che si verifichi un’eccezione o meno.
3. Spiega l’Gerarchia delle eccezioni di Java?
Le eccezioni di Java sono gerarchiche e l’ereditarietà viene utilizzata per categorizzare diversi tipi di eccezioni. `Throwable` è la classe padre della gerarchia delle eccezioni di Java e ha due oggetti figli – `Error` ed `Exception`. Le eccezioni sono ulteriormente divise in eccezioni controllate e eccezioni di runtime. Gli `Errors` sono scenari eccezionali che esulano dallo scope dell’applicazione e non è possibile prevedere e recuperare da essi, ad esempio, il fallimento dell’hardware, il crash del JVM o errori di memoria esaurita. Le `Checked Exceptions` sono scenari eccezionali che possiamo prevedere in un programma e cercare di recuperare da esso, ad esempio, `FileNotFoundException`. Dovremmo catturare questa eccezione e fornire un messaggio utile all’utente e registrarla correttamente per scopi di debug. `Exception` è la classe padre di tutte le eccezioni controllate. Le `Runtime Exceptions` sono causate da una cattiva programmazione, ad esempio, cercando di recuperare un elemento dall’array. Dovremmo controllare prima la lunghezza dell’array prima di provare a recuperare l’elemento, altrimenti potrebbe generare `ArrayIndexOutOfBoundsException` durante l’esecuzione. `RuntimeException` è la classe padre di tutte le eccezioni di runtime.
4. Quali sono i metodi importanti della classe Java Exception?
L’eccezione e tutte le sue sottoclassi non forniscono alcun metodo specifico e tutti i metodi sono definiti nella classe base Throwable.
- String getMessage() – Questo metodo restituisce la stringa del messaggio di Throwable e il messaggio può essere fornito durante la creazione dell’eccezione attraverso il suo costruttore.
- String getLocalizedMessage() – Questo metodo è fornito in modo che le sottoclassi possano sovrascriverlo per fornire i messaggi specifici della località al programma chiamante. L’implementazione della classe Throwable di questo metodo utilizza semplicemente il metodo
getMessage()
per restituire il messaggio dell’eccezione. - Throwable getCause() sincronizzato – Questo metodo restituisce la causa dell’eccezione o null se la causa è sconosciuta.
- String toString() – Questo metodo restituisce le informazioni su Throwable in formato Stringa, la Stringa restituita contiene il nome della classe Throwable e il messaggio localizzato.
- void printStackTrace() – Questo metodo stampa le informazioni sul tracciamento dello stack sul flusso di errore standard, questo metodo è sovraccaricato e possiamo passare PrintStream o PrintWriter come argomento per scrivere le informazioni sul tracciamento dello stack nel file o nello stream.
Spiega la funzionalità ARM di Java 7 e il blocco multi-catch?
Se stai catturando molte eccezioni in un singolo blocco try, noterai che il codice del blocco catch appare molto brutto e consiste principalmente in codice ridondante per registrare l’errore, tenendo presente questo, una delle caratteristiche di Java 7 era il blocco multi-catch dove possiamo catturare più eccezioni in un unico blocco catch. Il blocco catch con questa funzionalità appare come segue:
catch(IOException | SQLException | Exception ex){
logger.error(ex);
throw new MyException(ex.getMessage());
}
La maggior parte delle volte, usiamo il blocco finally solo per chiudere le risorse e talvolta ci dimentichiamo di chiuderle e otteniamo eccezioni in fase di esecuzione quando le risorse sono esaurite. Queste eccezioni sono difficili da debuggare e potremmo dover guardare in ogni punto in cui stiamo utilizzando quel tipo di risorsa per assicurarci di chiuderla. Quindi una delle migliorie di Java 7 era try-with-resources dove possiamo creare una risorsa nello stesso blocco try e usarla all’interno del blocco try-catch. Quando l’esecuzione esce dal blocco try-catch, l’ambiente di runtime chiude automaticamente queste risorse. Esempio di blocco try-catch con questa miglioria è:
try (MyResource mr = new MyResource()) {
System.out.println("MyResource created in try-with-resources");
} catch (Exception e) {
e.printStackTrace();
}
Leggi di più su questo su Java 7 ARM.
6. Qual è la differenza tra eccezioni controllate e non controllate in Java?
- Le eccezioni controllate devono essere gestite nel codice utilizzando il blocco try-catch o altrimenti il metodo dovrebbe utilizzare la parola chiave throws per informare il chiamante delle eccezioni controllate che potrebbero essere generate dal metodo. Le eccezioni non controllate non sono obbligate a essere gestite nel programma o menzionate nella clausola throws del metodo.
Exception
è la superclasse di tutte le eccezioni controllate mentreRuntimeException
è la superclasse di tutte le eccezioni non controllate. Nota che RuntimeException è la sottoclasse di Exception.- Le eccezioni controllate sono scenari di errore che devono essere gestiti nel codice, altrimenti si otterrà un errore di compilazione. Ad esempio, se si utilizza FileReader per leggere un file, viene generata un’eccezione
FileNotFoundException
e dobbiamo catturarla nel blocco try-catch o lanciarla di nuovo al metodo chiamante. Le eccezioni non controllate sono principalmente causate da una programmazione non adeguata, ad esempio, NullPointerException quando si invoca un metodo su un riferimento di oggetto senza assicurarsi che non sia null. Ad esempio, posso scrivere un metodo per rimuovere tutte le vocali dalla stringa. È responsabilità del chiamante assicurarsi di non passare una stringa nulla. Potrei modificare il metodo per gestire questi scenari ma idealmente, il chiamante dovrebbe occuparsene.
Qual è la differenza tra la parola chiave throw e throws in Java?
La parola chiave throws viene utilizzata con la firma del metodo per dichiarare le eccezioni che il metodo potrebbe generare, mentre la parola chiave throw viene utilizzata per interrompere il flusso del programma e trasferire l’oggetto eccezione al runtime per gestirlo.
8. Come scrivere eccezioni personalizzate in Java?
Possiamo estendere la classe Exception
o una delle sue sottoclassi per creare la nostra classe eccezione personalizzata. La classe eccezione personalizzata può avere le sue variabili e metodi che possiamo utilizzare per passare codici di errore o altre informazioni correlate all’eccezione all’handler dell’eccezione. Di seguito è mostrato un semplice esempio di eccezione personalizzata.
package com.journaldev.exceptions;
import java.io.IOException;
public class MyException extends IOException {
private static final long serialVersionUID = 4664456874499611218L;
private String errorCode="Unknown_Exception";
public MyException(String message, String errorCode){
super(message);
this.errorCode=errorCode;
}
public String getErrorCode(){
return this.errorCode;
}
}
9. Cos’è OutOfMemoryError in Java?
OutOfMemoryError in Java è una sottoclasse di java.lang.VirtualMachineError e viene lanciata dalla JVM quando si esaurisce la memoria heap. Possiamo risolvere questo errore fornendo più memoria per eseguire l’applicazione Java tramite le opzioni java. $>java MyProgram -Xms1024m -Xmx1024m -XX:PermSize=64M -XX:MaxPermSize=256m
10. Quali sono i diversi scenari che causano “Eccezione nel thread principale”?
Alcuni dei comuni scenari di eccezioni del thread principale sono:
- Eccezione nel thread principale java.lang.UnsupportedClassVersionError: Questa eccezione si verifica quando la classe Java è compilata da un’altra versione di JDK e si sta cercando di eseguirla da un’altra versione di Java.
- Eccezione nel thread principale java.lang.NoClassDefFoundError: Ci sono due varianti di questa eccezione. La prima è quando si fornisce il nome completo della classe con estensione .class. Il secondo scenario è quando la classe non viene trovata.
- Eccezione nel thread principale java.lang.NoSuchMethodError: main: Questa eccezione si verifica quando si sta cercando di eseguire una classe che non ha il metodo main.
- Eccezione nel thread “main” java.lang.ArithmeticException: Ogni volta che viene lanciata un’eccezione dal metodo principale, stampa l’eccezione nella console. La prima parte spiega che viene lanciata un’eccezione dal metodo principale, la seconda parte stampa il nome della classe dell’eccezione e quindi dopo due punti stampa il messaggio dell’eccezione.
Leggi di più su questo argomento su Java Exception in thread main.
11. Qual è la differenza tra final, finally e finalize in Java?
final e finally sono parole chiave in Java mentre finalize è un metodo. La parola chiave final può essere utilizzata con variabili di classe in modo che non possano essere riassegnate, con la classe per evitare l’estensione da parte di altre classi e con i metodi per evitare l’override da parte di sottoclassi, la parola chiave finally viene utilizzata con il blocco try-catch per fornire istruzioni che verranno sempre eseguite anche se si verifica un’eccezione, di solito finally viene utilizzato per chiudere le risorse. Il metodo finalize() viene eseguito dal Garbage Collector prima che l’oggetto venga distrutto, è un ottimo modo per assicurarsi che tutte le risorse globali siano chiuse. Tra le tre, solo finally è correlato alla gestione delle eccezioni in Java.
12. Cosa succede quando un’eccezione viene lanciata dal metodo principale?
Quando un’eccezione viene lanciata da un metodo main(), Java Runtime termina il programma e stampa il messaggio di eccezione e la traccia dello stack nella console di sistema.
13. Possiamo avere un blocco catch vuoto?
Possiamo avere un blocco catch vuoto, ma è un esempio di programmazione scorretta. Non dovremmo mai avere un blocco catch vuoto perché se l’eccezione viene catturata da quel blocco, non avremo informazioni sull’eccezione e sarà un incubo per il debug. Dovrebbe esserci almeno una istruzione di logging per registrare i dettagli dell’eccezione nella console o nei file di log.
14. Fornire alcune Best Practices per la Gestione delle Eccezioni in Java?
Alcune delle migliori pratiche relative alla Gestione delle Eccezioni in Java sono:
- Utilizzare eccezioni specifiche per facilitare il debug.
- Lancia eccezioni presto (Fallisci velocemente) nel programma.
- Cattura le eccezioni tardi nel programma, lascia che chi chiama gestisca l’eccezione.
- Utilizza la funzionalità ARM di Java 7 per assicurarti che le risorse siano chiuse oppure utilizza il blocco finally per chiuderle correttamente.
- Registra sempre i messaggi di eccezione per scopi di debug.
- Utilizza il blocco multi-catch per una chiusura più pulita.
- Utilizza eccezioni personalizzate per lanciare un singolo tipo di eccezione dall’API della tua applicazione.
- Segui la convenzione di denominazione, termina sempre con Exception.
- Documenta le eccezioni generate da un metodo utilizzando @throws nel javadoc.
- Le eccezioni sono costose, quindi lanciala solo quando ha senso. Altrimenti puoi catturarle e fornire una risposta nulla o vuota.
Leggi di più su di esse in dettaglio su Java Exception Handling Best Practices.
15. Qual è il problema con i programmi sottostanti e come possiamo risolverlo?
In questa sezione, esamineremo alcune domande di programmazione relative alle eccezioni Java.
-
Qual è il problema con il programma sottostante?
package com.journaldev.exceptions; import java.io.FileNotFoundException; import java.io.IOException; public class TestException { public static void main(String[] args) { try { testExceptions(); } catch (FileNotFoundException | IOException e) { e.printStackTrace(); } } public static void testExceptions() throws IOException, FileNotFoundException{ } }
Il programma sopra non compilerà e otterrai un messaggio di errore “L’eccezione FileNotFoundException è già catturata dall’alternativa IOException”. Questo perché FileNotFoundException è una sottoclasse di IOException, ci sono due modi per risolvere questo problema. Il primo modo è utilizzare un singolo blocco catch per entrambe le eccezioni.
try { testExceptions(); }catch(FileNotFoundException e){ e.printStackTrace(); }catch (IOException e) { e.printStackTrace(); }
Un altro modo è rimuovere FileNotFoundException dal blocco multi-catch.
try { testExceptions(); }catch (IOException e) { e.printStackTrace(); }
Puoi scegliere uno qualsiasi di questi approcci in base al codice del tuo blocco catch.
-
Qual è il problema con il programma qui sotto?
package com.journaldev.exceptions; import java.io.FileNotFoundException; import java.io.IOException; import javax.xml.bind.JAXBException; public class TestException1 { public static void main(String[] args) { try { go(); } catch (IOException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (JAXBException e) { e.printStackTrace(); } } public static void go() throws IOException, JAXBException, FileNotFoundException{ } }
Il programma non verrà compilato perché FileNotFoundException è una sottoclasse di IOException, quindi il blocco catch di FileNotFoundException è irraggiungibile e riceverai un messaggio di errore come “Unreachable catch block for FileNotFoundException. It is already handled by the catch block for IOException”. È necessario correggere l’ordine del blocco catch per risolvere questo problema.
try { go(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (JAXBException e) { e.printStackTrace(); }
Si noti che JAXBException non è correlato a IOException o FileNotFoundException e può essere posizionato ovunque nella gerarchia del blocco catch sopra.
-
Qual è il problema con il seguente programma?
package com.journaldev.exceptions; import java.io.IOException; import javax.xml.bind.JAXBException; public class TestException2 { public static void main(String[] args) { try { foo(); } catch (IOException e) { e.printStackTrace(); }catch(JAXBException e){ e.printStackTrace(); }catch(NullPointerException e){ e.printStackTrace(); }catch(Exception e){ e.printStackTrace(); } } public static void foo() throws IOException{ } }
Il programma non si compilerà perché JAXBException è un’eccezione verificata e il metodo foo() dovrebbe lanciare questa eccezione per catturare nel metodo chiamante. Otterrai un messaggio di errore come “Blocco catch non raggiungibile per JAXBException. Questa eccezione non viene mai lanciata dal corpo della dichiarazione try”. Per risolvere questo problema, dovrai rimuovere il blocco catch di JAXBException. Si noti che la cattura di NullPointerException è valida perché è un’eccezione non verificata.
-
Qual è il problema con il programma seguente?
package com.journaldev.exceptions; public class TestException3 { public static void main(String[] args) { try{ bar(); }catch(NullPointerException e){ e.printStackTrace(); }catch(Exception e){ e.printStackTrace(); } foo(); } public static void bar(){ } public static void foo() throws NullPointerException{ } }
Questa è una domanda trabocchetto, non c’è alcun problema nel codice e verrà compilato correttamente. Possiamo sempre catturare un’Eccezione o qualsiasi eccezione non controllata anche se non è presente nella clausola throws del metodo. Allo stesso modo, se un metodo (foo) dichiara un’eccezione non controllata nella clausola throws, non è obbligatorio gestirla nel programma.
-
Qual è il problema con il programma sottostante?
package com.journaldev.exceptions; import java.io.IOException; public class TestException4 { public void start() throws IOException{ } public void foo() throws NullPointerException{ } } class TestException5 extends TestException4{ public void start() throws Exception{ } public void foo() throws RuntimeException{ } }
Il programma sopra non verrà compilato perché la firma del metodo start() non è la stessa nella sottoclasse. Per risolvere questo problema, possiamo cambiare la firma del metodo nella sottoclasse in modo che sia esattamente la stessa della superclasse oppure possiamo rimuovere la clausola throws dal metodo della sottoclasse come mostrato di seguito.
@Override public void start(){ }
-
Qual è il problema con il programma sottostante?
package com.journaldev.exceptions; import java.io.IOException; import javax.xml.bind.JAXBException; public class TestException6 { public static void main(String[] args) { try { foo(); } catch (IOException | JAXBException e) { e = new Exception(""); e.printStackTrace(); }catch(Exception e){ e = new Exception(""); e.printStackTrace(); } } public static void foo() throws IOException, JAXBException{ } }
Il programma sopra non compilerà perché l’oggetto eccezione nel blocco multi-catch è finale e non possiamo cambiarne il valore. Otterrai un errore di compilazione come “Il parametro e di un blocco multi-catch non può essere assegnato”. Dobbiamo rimuovere l’assegnazione di “e” a un nuovo oggetto eccezione per risolvere questo errore. Leggi di più su blocco multi-catch di Java 7.
Questo è tutto per le domande di intervista sulle eccezioni Java, spero che ti siano piaciute. Ne aggiungerò altre alla lista in futuro, assicurati di aggiungerla ai segnalibri per un uso futuro.
Source:
https://www.digitalocean.com/community/tutorials/java-exception-interview-questions-and-answers