Fragen zu Java-Ausnahmen im Interview (Antworten)

Fragen im Vorstellungsgespräch für Java Exceptions (+ Antworten)

1. Überblick

Ausnahmen sind ein wesentliches Thema, mit dem jeder Java-Entwickler vertraut sein sollte. Dieser Artikel enthält Antworten auf einige der Fragen, die während eines Interviews auftreten können.

2. Fragen

Q1. Was ist eine Ausnahme?

Eine Ausnahme ist ein abnormales Ereignis, das während der Ausführung eines Programms auftritt und den normalen Ablauf der Programmanweisungen stört.

Q2. Was ist der Zweck der Throw- und Throws-Schlüsselwörter?

Das Schlüsselwortthrows wird verwendet, um anzugeben, dass eine Methode während ihrer Ausführung eine Ausnahme auslösen kann. Es erzwingt die explizite Ausnahmebehandlung beim Aufrufen einer Methode:

public void simpleMethod() throws Exception {
    // ...
}

Mit dem Schlüsselwortthrow können wir ein Ausnahmeobjekt auslösen, um den normalen Programmfluss zu unterbrechen. Dies wird am häufigsten verwendet, wenn ein Programm eine bestimmte Bedingung nicht erfüllt:

if (task.isTooComplicated()) {
    throw new TooComplicatedException("The task is too complicated");
}

Q3. Wie können Sie mit einer Ausnahme umgehen?

Mit einertry-catch-finally-Anweisung:

try {
    // ...
} catch (ExceptionType1 ex) {
    // ...
} catch (ExceptionType2 ex) {
    // ...
} finally {
    // ...
}

Der Codeblock, in dem eine Ausnahme auftreten kann, ist in einemtry-Block eingeschlossen. Dieser Block wird auch als "geschützter" oder "geschützter" Code bezeichnet.

Wenn eine Ausnahme auftritt, wird der Blockcatchausgeführt, der der ausgelösten Ausnahme entspricht. Andernfalls werden alle Blöckecatchignoriert.

Der Blockfinally wird immer ausgeführt, nachdem der Blocktrybeendet wurde, unabhängig davon, ob eine Ausnahme ausgelöst wurde oder nicht.

Q4. Wie können Sie mehrere Ausnahmen abfangen?

Es gibt drei Möglichkeiten, mehrere Ausnahmen in einem Codeblock zu behandeln.

Der erste besteht darin, einencatch-Block zu verwenden, der alle ausgelösten Ausnahmetypen verarbeiten kann:

try {
    // ...
} catch (Exception ex) {
    // ...
}

Beachten Sie, dass die empfohlene Vorgehensweise darin besteht, Ausnahmebehandlungsroutinen zu verwenden, die so genau wie möglich sind.

Zu breite Ausnahmebehandlungsroutinen können Ihren Code fehleranfälliger machen, nicht erwartete Ausnahmen abfangen und unerwartetes Verhalten in Ihrem Programm verursachen.

Der zweite Weg ist die Implementierung mehrerer catch-Blöcke:

try {
    // ...
} catch (FileNotFoundException ex) {
    // ...
} catch (EOFException ex) {
    // ...
}

Beachten Sie, dass, wenn die Ausnahmen eine Vererbungsbeziehung haben; Der untergeordnete Typ muss an erster Stelle und der übergeordnete Typ später stehen. Wenn wir dies nicht tun, führt dies zu einem Kompilierungsfehler.

Der dritte ist die Verwendung eines Multi-Catch-Blocks:

try {
    // ...
} catch (FileNotFoundException | EOFException ex) {
    // ...
}

Diese Funktion wurde erstmals in Java 7 eingeführt. Reduziert die Codeduplizierung und erleichtert die Wartung.

Q5. Was ist der Unterschied zwischen einer geprüften und einer ungeprüften Ausnahme?

Eine aktivierte Ausnahme muss innerhalb einestry-catch-Blocks behandelt oder in einerthrows-Klausel deklariert werden. Eine ungeprüfte Ausnahme muss weder behandelt noch deklariert werden.

Aktivierte und deaktivierte Ausnahmen werden auch als Compile-Time- bzw. Runtime-Ausnahmen bezeichnet.

Alle Ausnahmen sind geprüfte Ausnahmen, mit Ausnahme der durchError,RuntimeException und ihre Unterklassen angegebenen.

Q6. Was ist der Unterschied zwischen einer Ausnahme und einem Fehler?

Eine Ausnahme ist ein Ereignis, das einen Zustand darstellt, bei dem eine Wiederherstellung möglich ist, während ein Fehler eine externe Situation darstellt, bei der normalerweise keine Wiederherstellung möglich ist.

Alle von der JVM ausgelösten Fehler sind Instanzen vonError oder einer ihrer Unterklassen. Die häufigsten Fehler umfassen, sind aber nicht beschränkt auf:

  • OutOfMemoryError - Wird ausgelöst, wenn die JVM keine weiteren Objekte zuordnen kann, weil der Speicher knapp ist und der Garbage Collector nicht mehr verfügbar machen konnte

  • StackOverflowError - tritt auf, wenn der Stapelspeicher für einen Thread aufgebraucht ist, normalerweise weil eine Anwendung zu tief rekursiv ist

  • ExceptionInInitializerError - signalisiert, dass während der Auswertung eines statischen Initialisierers eine unerwartete Ausnahme aufgetreten ist

  • NoClassDefFoundError - wird ausgelöst, wenn der Klassenladeprogramm versucht, die Definition einer Klasse zu laden und sie nicht finden konnte, normalerweise, weil die erforderlichenclass-Dateien nicht im Klassenpfad gefunden wurden

  • UnsupportedClassVersionError - tritt auf, wenn die JVM versucht, eineclass-Datei zu lesen, und feststellt, dass die Version in der Datei nicht unterstützt wird, normalerweise, weil die Datei mit einer neueren Java-Version generiert wurde

Obwohl ein Fehler mit einertry-Anweisung behandelt werden kann, wird dies nicht empfohlen, da nicht garantiert werden kann, dass das Programm nach dem Auslösen des Fehlers zuverlässig etwas tun kann.

Q7. Welche Ausnahme wird beim Ausführen des folgenden Codeblocks ausgelöst?

Integer[][] ints = { { 1, 2, 3 }, { null }, { 7, 8, 9 } };
System.out.println("value = " + ints[1][1].intValue());

Es wird einArrayIndexOutOfBoundsException ausgelöst, da wir versuchen, auf eine Position zuzugreifen, die größer als die Länge des Arrays ist.

Q8. Was ist Ausnahmeverkettung?

Tritt ein, wenn eine Ausnahme als Antwort auf eine andere Ausnahme ausgelöst wird. Auf diese Weise können wir die gesamte Geschichte unseres aufgeworfenen Problems entdecken:

try {
    task.readConfigFile();
} catch (FileNotFoundException ex) {
    throw new TaskException("Could not perform task", ex);
}

Q9. Was ist ein Stacktrace und wie hängt er mit einer Ausnahme zusammen?

Ein Stack-Trace enthält die Namen der Klassen und Methoden, die vom Start der Anwendung bis zum Auftreten einer Ausnahme aufgerufen wurden.

Es ist ein sehr nützliches Debugging-Tool, mit dem wir genau bestimmen können, wo die Ausnahme in der Anwendung ausgelöst wurde und welche ursprünglichen Ursachen dazu geführt haben.

Q10. Warum sollten Sie eine Ausnahme unterordnen?

Wenn der Ausnahmetyp nicht durch diejenigen dargestellt wird, die bereits auf der Java-Plattform vorhanden sind, oder wenn Sie mehr Informationen zum Clientcode bereitstellen müssen, um ihn genauer zu behandeln, sollten Sie eine benutzerdefinierte Ausnahme erstellen.

Die Entscheidung, ob eine benutzerdefinierte Ausnahme aktiviert oder deaktiviert werden soll, hängt vollständig vom Geschäftsfall ab. Als Faustregel gilt jedoch: Wenn zu erwarten ist, dass der Code, der Ihre Ausnahme verwendet, wiederhergestellt wird, erstellen Sie eine aktivierte Ausnahme, andernfalls deaktivieren Sie diese.

Außerdem sollten Sie von der spezifischstenException-Unterklasse erben, die eng mit der Unterklasse zusammenhängt, die Sie werfen möchten. Wenn es keine solche Klasse gibt, wählen SieException als übergeordnetes Element.

Q11. Was sind einige Vorteile von Ausnahmen?

Herkömmliche Fehlererkennungs- und -behandlungstechniken führen häufig dazu, dass der Spaghetti-Code schwer zu warten und schwer zu lesen ist. Ausnahmen ermöglichen es uns jedoch, die Kernlogik unserer Anwendung von den Details zu trennen, die zu tun sind, wenn etwas Unerwartetes passiert.

Da die JVM den Aufrufstapel rückwärts durchsucht, um Methoden zu finden, die an der Behandlung einer bestimmten Ausnahme interessiert sind, gilt Folgendes: Wir erhalten die Möglichkeit, einen Fehler im Aufrufstapel weiterzugeben, ohne zusätzlichen Code zu schreiben.

Da alle in einem Programm ausgelösten Ausnahmen Objekte sind, können sie basierend auf ihrer Klassenhierarchie gruppiert oder kategorisiert werden. Auf diese Weise können wir Gruppenausnahmen in einem einzelnen Ausnahmebehandler abfangen, indem wir die Oberklasse der Ausnahme im Blockcatchangeben.

Q12. Können Sie eine Ausnahme in den Körper eines Lambda-Ausdrucks werfen?

Wenn Sie eine Standardfunktionsschnittstelle verwenden, die bereits von Java bereitgestellt wird, können Sie nur ungeprüfte Ausnahmen auslösen, da Standardfunktionsschnittstellen keine Throws-Klausel in Methodensignaturen enthalten:

List integers = Arrays.asList(3, 9, 7, 0, 10, 20);
integers.forEach(i -> {
    if (i == 0) {
        throw new IllegalArgumentException("Zero not allowed");
    }
    System.out.println(Math.PI / i);
});

Wenn Sie jedoch eine benutzerdefinierte Funktionsschnittstelle verwenden, ist das Auslösen von aktivierten Ausnahmen möglich:

@FunctionalInterface
public static interface CheckedFunction {
    void apply(T t) throws Exception;
}
public void processTasks(
  List taks, CheckedFunction checkedFunction) {
    for (Task task : taks) {
        try {
            checkedFunction.apply(task);
        } catch (Exception e) {
            // ...
        }
    }
}

processTasks(taskList, t -> {
    // ...
    throw new Exception("Something happened");
});

Q13. Welche Regeln müssen wir befolgen, wenn wir eine Methode überschreiben, die eine Ausnahme auslöst?

Verschiedene Regeln bestimmen, wie Ausnahmen im Zusammenhang mit der Vererbung deklariert werden müssen.

Wenn die übergeordnete Klassenmethode keine Ausnahmen auslöst, kann die untergeordnete Klassenmethode keine aktivierte Ausnahme auslösen, jedoch möglicherweise keine deaktivierte.

Hier ist ein Beispielcode, um dies zu demonstrieren:

class Parent {
    void doSomething() {
        // ...
    }
}

class Child extends Parent {
    void doSomething() throws IllegalArgumentException {
        // ...
    }
}

Das nächste Beispiel kann nicht kompiliert werden, da die überschreibende Methode eine überprüfte Ausnahme auslöst, die in der überschriebenen Methode nicht deklariert ist:

class Parent {
    void doSomething() {
        // ...
    }
}

class Child extends Parent {
    void doSomething() throws IOException {
        // Compilation error
    }
}

Wenn die übergeordnete Klassenmethode eine oder mehrere aktivierte Ausnahmen auslöst, kann die untergeordnete Klassenmethode jede nicht aktivierte Ausnahme auslösen. alle, keine oder eine Teilmenge der deklarierten geprüften Ausnahmen und sogar eine größere Anzahl davon, sofern sie den gleichen oder engeren Geltungsbereich haben.

Hier ist ein Beispielcode, der der vorherigen Regel erfolgreich folgt:

class Parent {
    void doSomething() throws IOException, ParseException {
        // ...
    }

    void doSomethingElse() throws IOException {
        // ...
    }
}

class Child extends Parent {
    void doSomething() throws IOException {
        // ...
    }

    void doSomethingElse() throws FileNotFoundException, EOFException {
        // ...
    }
}

Beachten Sie, dass beide Methoden die Regel einhalten. Die erste löst weniger Ausnahmen aus als die überschriebene Methode und die zweite, obwohl sie mehr auslöst. Ihr Umfang ist enger.

Wenn wir jedoch versuchen, eine aktivierte Ausnahme auszulösen, die von der übergeordneten Klassenmethode nicht deklariert wird, oder eine Ausnahme mit einem breiteren Gültigkeitsbereich auslösen. Es wird ein Kompilierungsfehler angezeigt:

class Parent {
    void doSomething() throws FileNotFoundException {
        // ...
    }
}

class Child extends Parent {
    void doSomething() throws IOException {
        // Compilation error
    }
}

Wenn die übergeordnete Klassenmethode eine throws-Klausel mit einer ungeprüften Ausnahme enthält, kann die untergeordnete Klassenmethode keine oder eine beliebige Anzahl ungeprüfter Ausnahmen auslösen, auch wenn sie nicht miteinander verknüpft sind.

Hier ist ein Beispiel, das die Regel einhält:

class Parent {
    void doSomething() throws IllegalArgumentException {
        // ...
    }
}

class Child extends Parent {
    void doSomething()
      throws ArithmeticException, BufferOverflowException {
        // ...
    }
}

Q14. Wird der folgende Code kompiliert?

void doSomething() {
    // ...
    throw new RuntimeException(new Exception("Chained Exception"));
}

Yes. Bei der Verkettung von Ausnahmen kümmert sich der Compiler nur um die erste in der Kette. Da eine nicht aktivierte Ausnahme erkannt wird, müssen wir keine Throws-Klausel hinzufügen.

Q15. Gibt es eine Möglichkeit, eine überprüfte Ausnahme von einer Methode zu werfen, die keine Wurfklausel enthält?

Yes. Wir können die vom Compiler durchgeführte Typlöschung nutzen und den Eindruck erwecken, dass wir eine ungeprüfte Ausnahme auslösen, wenn tatsächlich; Wir lösen eine aktivierte Ausnahme aus:

public  T sneakyThrow(Throwable ex) throws T {
    throw (T) ex;
}

public void methodWithoutThrows() {
    this.sneakyThrow(new Exception("Checked Exception"));
}

3. Fazit

In diesem Artikel haben wir uns mit einigen Fragen befasst, die in technischen Interviews für Java-Entwickler zu Ausnahmen auftreten können. Dies ist keine erschöpfende Liste und sollte nur als Beginn weiterer Forschungen betrachtet werden.

Wir wünschen Ihnen zum Beispiel viel Erfolg bei bevorstehenden Interviews.