Java bietet einen robusten und objektorientierten Ansatz zur Behandlung von Ausnahmeszenarien, bekannt als Java-Ausnahmebehandlung. Vor einiger Zeit habe ich einen langen Beitrag zur Ausnahmebehandlung in Java geschrieben, und heute liste ich einige wichtige Java-Ausnahme-Fragen mit Antworten auf, um Ihnen bei Vorstellungsgesprächen zu helfen.
- Was ist eine Ausnahme in Java?
- Was sind die Schlüsselwörter für die Ausnahmebehandlung in Java?
- Erklären Sie die Java-Ausnahme-Hierarchie?
- Was sind die wichtigen Methoden der Java-Ausnahme-Klasse?
- Erklären Sie das Java 7 ARM-Feature und den Multi-Catch-Block?
- Was ist der Unterschied zwischen überprüften und nicht überprüften Ausnahmen in Java?
- Was ist der Unterschied zwischen den Schlüsselwörtern throw und throws in Java?
- Wie schreibt man benutzerdefinierte Ausnahmen in Java?
- Was ist OutOfMemoryError in Java?
- Welche verschiedenen Szenarien verursachen „Ausnahme im Hauptthread“?
- Was ist der Unterschied zwischen final, finally und finalize in Java?
- Was passiert, wenn eine Ausnahme von der Hauptmethode ausgelöst wird?
- Können wir einen leeren Catch-Block haben?
- Geben Sie einige bewährte Praktiken für die Java-Fehlerbehandlung an?
- Was ist das Problem mit den untenstehenden Programmen und wie beheben wir es?
1. Was ist eine Ausnahme in Java?
Eine Ausnahme ist ein Fehlerereignis, das während der Ausführung eines Programms auftreten kann und den normalen Ablauf stört. Die Ausnahme kann aus verschiedenen Situationen wie falschen vom Benutzer eingegebenen Daten, Hardwarefehlern, Netzwerkverbindungsfehlern usw. resultieren. Immer wenn ein Fehler während der Ausführung einer Java-Anweisung auftritt, wird ein Ausnahmeobjekt erstellt und dann versucht die JRE, einen Ausnahmebehandler zu finden, um die Ausnahme zu behandeln. Wenn ein geeigneter Ausnahmebehandler gefunden wird, wird das Ausnahmeobjekt an den Handlercode übergeben, um die Ausnahme zu verarbeiten, was als Aufzeichnen der Ausnahme bezeichnet wird. Wenn kein Handler gefunden wird, wirft die Anwendung die Ausnahme an die Laufzeitumgebung und die JRE beendet das Programm. Das Java-Ausnahmebehandlungs-Framework wird nur verwendet, um Laufzeitfehler zu behandeln, Kompilierungsfehler werden nicht vom Ausnahmebehandlungsframework behandelt.
2. Was sind die Schlüsselwörter für die Ausnahmebehandlung in Java?
Es gibt vier Schlüsselwörter, die in der Java-Ausnahmebehandlung verwendet werden.
- throw: Manchmal möchten wir explizit ein Ausnahmeobjekt erstellen und es dann werfen, um die normale Verarbeitung des Programms zu stoppen. Das Schlüsselwort throw wird verwendet, um Ausnahmen an die Laufzeit weiterzugeben, die sie behandeln soll.
- throws: Wenn wir eine überprüfte Ausnahme in einer Methode werfen und sie nicht behandeln, müssen wir das Schlüsselwort
throws
in der Methodensignatur verwenden, um dem Aufruferprogramm die Ausnahmen mitzuteilen, die von der Methode ausgelöst werden könnten. Die Aufrufmethode kann diese Ausnahmen behandeln oder mit dem throws Schlüsselwort an ihre Aufrufermethode weitergeben. Wir können mehrere Ausnahmen in der throws-Klausel angeben, und sie kann auch mit der main()-Methode verwendet werden. - try-catch: Wir verwenden den try-catch-Block zur Ausnahmebehandlung in unserem Code. try ist der Beginn des Blocks und catch befindet sich am Ende des try-Blocks, um die Ausnahmen zu behandeln. Wir können mehrere catch-Blöcke mit einem try haben, und try-catch-Blöcke können ebenfalls verschachtelt sein. Der catch-Block erfordert einen Parameter, der vom Typ Ausnahme sein sollte.
- Endlich: Der finally-Block ist optional und kann nur mit einem try-catch-Block verwendet werden. Da eine Ausnahme den Ausführungsprozess stoppt, könnten einige Ressourcen geöffnet sein, die nicht geschlossen werden. Daher können wir den finally-Block verwenden. Der finally-Block wird immer ausgeführt, unabhängig davon, ob eine Ausnahme auftritt oder nicht.
3. Erkläre die Java-Ausnahmehierarchie?
Java-Ausnahmen sind hierarchisch strukturiert und Vererbung wird verwendet, um verschiedene Arten von Ausnahmen zu kategorisieren. Throwable
ist die Elternklasse der Java-Ausnahmenhierarchie und hat zwei Kindobjekte – Error
und Exception
. Ausnahmen werden weiter unterteilt in überprüfte Ausnahmen und Laufzeitausnahmen. Fehler sind außergewöhnliche Szenarien, die außerhalb des Anwendungsbereichs liegen und nicht vorhersehbar sind, zum Beispiel Hardwarefehler, JVM-Absturz oder Speicherfehler. Überprüfte Ausnahmen sind außergewöhnliche Szenarien, die wir in einem Programm voraussehen können und versuchen, uns davon zu erholen, zum Beispiel FileNotFoundException. Wir sollten diese Ausnahme abfangen und dem Benutzer eine nützliche Nachricht bereitstellen und sie ordnungsgemäß zur Fehlerbehebung protokollieren. Exception
ist die Elternklasse aller überprüften Ausnahmen. Laufzeitausnahmen werden durch schlechtes Programmieren verursacht, zum Beispiel der Versuch, ein Element aus dem Array abzurufen. Wir sollten zuerst die Länge des Arrays überprüfen, bevor wir versuchen, das Element abzurufen, da sonst möglicherweise ArrayIndexOutOfBoundException
während der Laufzeit ausgelöst wird. RuntimeException
ist die Elternklasse aller Laufzeitausnahmen.
4. Was sind die wichtigen Methoden der Java Exception-Klasse?
Exception und alle ihre Unterklassen bieten keine spezifischen Methoden an, und alle Methoden sind in der Basisklasse Throwable definiert.
- String getMessage() – Diese Methode gibt den Nachrichten-String von Throwable zurück, und die Nachricht kann beim Erstellen der Ausnahme über ihren Konstruktor bereitgestellt werden.
- String getLocalizedMessage() – Diese Methode wird bereitgestellt, damit Unterklassen sie überschreiben können, um lokalisierte Nachrichten für das aufrufende Programm bereitzustellen. Die Implementierung dieser Methode in der Throwable-Klasse verwendet einfach die
getMessage()
-Methode, um die Ausnahmemeldung zurückzugeben. - synchronized Throwable getCause() – Diese Methode gibt die Ursache der Ausnahme zurück oder null, wenn die Ursache unbekannt ist.
- String toString() – Diese Methode gibt Informationen zu Throwable im String-Format zurück. Der zurückgegebene String enthält den Namen der Throwable-Klasse und die lokalisierte Nachricht.
- void printStackTrace() – Diese Methode gibt die Stack-Trace-Informationen auf dem Standardfehlerausgabestream aus. Diese Methode ist überladen, und wir können PrintStream oder PrintWriter als Argument übergeben, um die Stack-Trace-Informationen in die Datei oder den Stream zu schreiben.
5. Erläutern Sie das Java 7 ARM-Feature und den Multi-Catch-Block?
Wenn Sie eine Vielzahl von Ausnahmen in einem einzigen Try-Block abfangen, werden Sie feststellen, dass der Code im Catch-Block sehr unübersichtlich aussieht und hauptsächlich aus redundantem Code besteht, um den Fehler zu protokollieren. Vor diesem Hintergrund war eine der Funktionen von Java 7 der Multi-Catch-Block, mit dem wir mehrere Ausnahmen in einem einzigen Catch-Block abfangen können. Der Catch-Block mit dieser Funktion sieht wie folgt aus:
catch(IOException | SQLException | Exception ex){
logger.error(ex);
throw new MyException(ex.getMessage());
}
Oft verwenden wir den Finally-Block nur, um die Ressourcen zu schließen, und manchmal vergessen wir, sie zu schließen, und erhalten Laufzeitfehler, wenn die Ressourcen erschöpft sind. Diese Ausnahmen sind schwer zu debuggen, und wir müssen möglicherweise jeden Ort überprüfen, an dem wir diese Art von Ressource verwenden, um sicherzustellen, dass wir sie schließen. Daher war eine der Verbesserungen von Java 7 das Try-with-Resources, mit dem wir eine Ressource im Try-Statement selbst erstellen und sie im Try-Catch-Block verwenden können. Wenn die Ausführung den Try-Catch-Block verlässt, schließt die Laufzeitumgebung diese Ressourcen automatisch. Ein Beispiel für einen Try-Catch-Block mit dieser Verbesserung ist:
try (MyResource mr = new MyResource()) {
System.out.println("MyResource created in try-with-resources");
} catch (Exception e) {
e.printStackTrace();
}
Weitere Informationen dazu finden Sie unter Java 7 ARM.
6. Was ist der Unterschied zwischen überprüften und unbeachteten Ausnahmen in Java?
- Überprüfte Ausnahmen müssen im Code mit einem try-catch-Block behandelt werden oder die Methode sollte das throws-Schlüsselwort verwenden, um den Aufrufer über die überprüften Ausnahmen zu informieren, die aus der Methode geworfen werden könnten. Ungeprüfte Ausnahmen müssen im Programm nicht behandelt werden oder in der throws-Klausel der Methode erwähnt werden.
Exception
ist die Superklasse aller überprüften Ausnahmen, währendRuntimeException
die Superklasse aller unbeachteten Ausnahmen ist. Beachten Sie, dass RuntimeException die Unterklasse von Exception ist.- Überprüfte Ausnahmen sind Fehlerfälle, die im Code behandelt werden müssen, sonst erhalten Sie einen Kompilierungsfehler. Wenn Sie beispielsweise FileReader zum Lesen einer Datei verwenden, wirft es
FileNotFoundException
, und wir müssen es im try-catch-Block abfangen oder erneut an die aufrufende Methode werfen. Ungeprüfte Ausnahmen werden meistens durch schlechtes Programmieren verursacht, zum Beispiel NullPointerException beim Aufrufen einer Methode über eine Objektreferenz, ohne sicherzustellen, dass sie nicht null ist. Ich könnte beispielsweise eine Methode schreiben, um alle Vokale aus dem String zu entfernen. Es liegt in der Verantwortung des Aufrufers, sicherzustellen, dass kein null-String übergeben wird. Ich könnte die Methode ändern, um diese Szenarien zu behandeln, aber idealerweise sollte sich der Aufrufer darum kümmern.
7. Was ist der Unterschied zwischen dem throw- und dem throws-Schlüsselwort in Java?
Das Schlüsselwort „throws“ wird mit der Methodensignatur verwendet, um die Ausnahmen zu deklarieren, die die Methode möglicherweise wirft, während das Schlüsselwort „throw“ verwendet wird, um den Programmfluss zu unterbrechen und das Ausnahmeobjekt an die Laufzeit zu übergeben, um es zu behandeln.
8. Wie schreibt man benutzerdefinierte Ausnahmen in Java?
Wir können die Klasse Exception
oder eine ihrer Unterklassen erweitern, um unsere benutzerdefinierte Ausnahmeklasse zu erstellen. Die benutzerdefinierte Ausnahmeklasse kann ihre eigenen Variablen und Methoden haben, die wir verwenden können, um Fehlercodes oder andere informationsbezogene Ausnahmeinformationen an den Ausnahmebehandler zu übergeben. Ein einfaches Beispiel für eine benutzerdefinierte Ausnahme wird unten gezeigt.
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. Was ist OutOfMemoryError in Java?
OutOfMemoryError in Java ist eine Unterklasse von java.lang.VirtualMachineError und wird von der JVM geworfen, wenn ihr der Speicher im Heap ausgeht. Wir können diesen Fehler beheben, indem wir der Java-Anwendung mehr Speicher durch Java-Optionen zuweisen. $>java MyProgram -Xms1024m -Xmx1024m -XX:PermSize=64M -XX:MaxPermSize=256m
10. Was sind verschiedene Szenarien, die zu „Exception in thread main“ führen?
Einige der häufigsten Szenarien für Ausnahmen im Hauptthread sind:
- Ausnahme im Hauptthread java.lang.UnsupportedClassVersionError: Diese Ausnahme tritt auf, wenn Ihre Java-Klasse aus einer anderen JDK-Version kompiliert wurde und Sie versuchen, sie aus einer anderen Java-Version auszuführen.
- Ausnahme im Hauptthread java.lang.NoClassDefFoundError: Es gibt zwei Varianten dieser Ausnahme. Die erste tritt auf, wenn Sie den vollständigen Klassennamen mit der .class-Erweiterung angeben. Das zweite Szenario tritt auf, wenn die Klasse nicht gefunden wird.
- Ausnahme im Hauptthread java.lang.NoSuchMethodError: main: Diese Ausnahme tritt auf, wenn Sie versuchen, eine Klasse auszuführen, die keine Hauptmethode hat.
- Ausnahme im Thread „main“ java.lang.ArithmeticException: Immer wenn eine Ausnahme aus der main-Methode geworfen wird, wird die Ausnahme in der Konsole ausgegeben. Der erste Teil erklärt, dass eine Ausnahme aus der main-Methode geworfen wird, der zweite Teil gibt den Namen der Ausnahme-Klasse aus und danach, nach einem Doppelpunkt, wird die Ausnahme-Nachricht ausgegeben.
Lesen Sie mehr darüber unter Java Ausnahme im Thread main.
11. Was ist der Unterschied zwischen final, finally und finalize in Java?
final und finally sind Schlüsselwörter in Java, während finalize eine Methode ist. Das Schlüsselwort final kann mit Klassenvariablen verwendet werden, damit sie nicht neu zugewiesen werden können, mit der Klasse, um die Erweiterung durch Klassen zu verhindern, und mit Methoden, um das Überschreiben durch Unterklassen zu verhindern. Das Schlüsselwort finally wird mit dem try-catch-Block verwendet, um Anweisungen bereitzustellen, die immer ausgeführt werden, selbst wenn eine Ausnahme auftritt. Normalerweise wird finally verwendet, um Ressourcen zu schließen. Die Methode finalize() wird vom Garbage Collector ausgeführt, bevor das Objekt zerstört wird. Es ist eine gute Möglichkeit sicherzustellen, dass alle globalen Ressourcen geschlossen sind. Von den dreien ist nur finally mit der Behandlung von Java-Ausnahmen verbunden.
12. Was passiert, wenn eine Ausnahme von der Hauptmethode ausgelöst wird?
Wenn eine Ausnahme von einer main() Methode ausgelöst wird, beendet die Java-Runtime das Programm und gibt die Ausnahmemeldung sowie den Stack-Trace in der Systemkonsole aus.
13. Können wir einen leeren Catch-Block haben?
Wir können einen leeren Catch-Block haben, aber das ist ein Beispiel für schlechte Programmierung. Wir sollten niemals einen leeren Catch-Block haben, denn wenn die Ausnahme von diesem Block abgefangen wird, haben wir keine Informationen über die Ausnahme und es wird ein Albtraum sein, sie zu debuggen. Es sollte mindestens eine Protokollierungsanweisung geben, um die Ausnahmedetails in der Konsole oder in Protokolldateien zu protokollieren.
14. Nennen Sie einige bewährte Methoden für die Java-Ausnahmebehandlung?
Einige bewährte Methoden im Zusammenhang mit der Java-Ausnahmebehandlung sind:
- Verwenden Sie spezifische Ausnahmen für eine einfache Fehlersuche.
- Werfen Sie Ausnahmen früh (Fail-Fast) im Programm.
- Fangen Sie Ausnahmen spät im Programm ab, lassen Sie den Aufrufer die Ausnahme behandeln.
- Verwenden Sie das Java-7-ARM-Feature, um sicherzustellen, dass Ressourcen geschlossen werden, oder verwenden Sie einen finally-Block, um sie ordnungsgemäß zu schließen.
- Loggen Sie immer Ausnahmemeldungen zu Debugging-Zwecken.
- Verwenden Sie einen Multi-Catch-Block für sauberes Schließen.
- Verwenden Sie benutzerdefinierte Ausnahmen, um einen einzelnen Ausnahmetyp aus Ihrer Anwendungs-API zu werfen.
- Befolgen Sie Namenskonventionen, enden Sie immer mit Exception.
- Dokumentieren Sie die von einer Methode ausgelösten Ausnahmen mit @throws in der Javadoc.
- Ausnahmen sind kostspielig, werfen Sie sie also nur, wenn es sinnvoll ist. Andernfalls können Sie sie abfangen und eine Null- oder Leerantwort bereitstellen.
Erfahren Sie mehr darüber im Detail unter Java Exception Handling Best Practices.
15. Was ist das Problem mit den unten stehenden Programmen und wie beheben wir es?
In diesem Abschnitt werden wir uns einige Programmierfragen im Zusammenhang mit Java-Ausnahmen ansehen.
-
Was ist das Problem mit dem unten stehenden Programm?
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{ } }
Das obige Programm wird nicht kompiliert und Sie erhalten eine Fehlermeldung „Die Ausnahme FileNotFoundException wird bereits durch die alternative IOException abgefangen“. Dies liegt daran, dass FileNotFoundException eine Unterklasse von IOException ist. Es gibt zwei Möglichkeiten, dieses Problem zu lösen. Der erste Weg besteht darin, einen einzigen Catch-Block für beide Ausnahmen zu verwenden.
try { testExceptions(); }catch(FileNotFoundException e){ e.printStackTrace(); }catch (IOException e) { e.printStackTrace(); }
Ein weiterer Weg besteht darin, FileNotFoundException aus dem Multi-Catch-Block zu entfernen.
try { testExceptions(); }catch (IOException e) { e.printStackTrace(); }
Sie können einen dieser Ansätze basierend auf Ihrem Catch-Block-Code wählen.
-
Was ist das Problem mit dem folgenden Programm?
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{ } }
Das Programm wird nicht kompiliert, weil FileNotFoundException eine Unterklasse von IOException ist, sodass der Catch-Block von FileNotFoundException unerreichbar ist und Sie eine Fehlermeldung erhalten, die besagt: „Unerreichbarer Catch-Block für FileNotFoundException. Er wird bereits durch den Catch-Block für IOException behandelt“. Sie müssen die Reihenfolge der Catch-Blöcke ändern, um dieses Problem zu lösen.
try { go(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (JAXBException e) { e.printStackTrace(); }
Beachten Sie, dass JAXBException nicht mit IOException oder FileNotFoundException zusammenhängt und an beliebiger Stelle in der obigen Catch-Block-Hierarchie platziert werden kann.
-
Was ist das Problem mit dem untenstehenden Programm?
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{ } }
Das Programm wird nicht kompiliert, weil JAXBException eine überprüfbare Ausnahme ist und die Methode foo() diese Ausnahme werfen sollte, um sie in der aufrufenden Methode zu fangen. Sie erhalten eine Fehlermeldung wie „Unreachable catch block for JAXBException. This exception is never thrown from the try statement body“. Um dieses Problem zu lösen, müssen Sie den catch-Block von JAXBException entfernen. Beachten Sie, dass das Fangen von NullPointerException gültig ist, da es sich um eine nicht überprüfbare Ausnahme handelt.
-
Was ist das Problem mit dem folgenden Programm?
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{ } }
Das ist eine trickreiche Frage, es gibt kein Problem mit dem Code und er wird erfolgreich kompiliert. Wir können immer eine Exception oder eine unbehandelte Ausnahme abfangen, auch wenn sie nicht im throws-Klausel der Methode steht. Ebenso ist es nicht zwingend erforderlich, eine unbehandelte Ausnahme in einem Programm zu behandeln, wenn eine Methode (foo) eine unbehandelte Ausnahme in der throws-Klausel deklariert.
-
Was ist das Problem mit dem untenstehenden Programm?
Paket com.journaldev.exceptions; import java.io.IOException; public class TestException4 { public void start() wirft IOException{ } public void foo() wirft NullPointerException{ } } Klasse TestException5 erweitert TestException4{ public void start() wirft Exception{ } public void foo() wirft RuntimeException{ } }
Das obenstehende Programm wird nicht kompilieren, weil die Signatur der Methode start() in der Unterklasse nicht mit der der Superklasse übereinstimmt. Um dieses Problem zu beheben, können wir entweder die Methodensignatur in der Unterklasse genau wie in der Superklasse ändern oder die throws-Klausel aus der Methodendeklaration der Unterklasse entfernen, wie unten gezeigt.
@Override public void start(){ }
-
Was ist das Problem mit dem untenstehenden Programm?
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{ } }
Das obige Programm wird nicht kompiliert, da das Ausnahmeobjekt im Multi-Catch-Block final ist und wir seinen Wert nicht ändern können. Sie erhalten einen Kompilierungsfehler „Der Parameter e eines Multi-Catch-Blocks kann nicht zugewiesen werden“. Wir müssen die Zuweisung von „e“ zu einem neuen Ausnahmeobjekt entfernen, um diesen Fehler zu beheben. Lesen Sie mehr unter Java 7 Multi-Catch-Block.
Das ist alles für die Java-Ausnahmeinterviewfragen, ich hoffe, sie gefallen Ihnen. Ich werde in Zukunft mehr zur Liste hinzufügen, stellen Sie sicher, dass Sie sie zum späteren Gebrauch bookmarken.
Source:
https://www.digitalocean.com/community/tutorials/java-exception-interview-questions-and-answers