Abfangen mehrerer Ausnahmen in Java-8

Lesezeit: 3 Minuten

Benutzer-Avatar
T-Tasche

Beim Ausprobieren der Mehrfachfang Funktion, die ich in meinem gefunden habe m1() Methode funktioniert alles wie erwartet.

Allerdings hinein m2() derselbe Code wird nicht kompiliert. Ich habe nur die Syntax geändert, um die Anzahl der Codezeilen zu reduzieren.

public class Main {

    public int m1(boolean bool) {
        try {
            if (bool) {
                throw new Excep1();
            }
            throw new Excep2();
            //This m1() is compiling  abs fine.
        } catch (Excep1 | Excep2 e) {
            return 0;
        }
    }

    public int m2(boolean b) {
        try {
            throw b ? new Excep1() : new Excep2();
            //This one is not compiling.
        } catch (Excep1 | Excep2 e) {
            return 0;
        }
    }

    private static interface I {
    }

    private static class Excep1 extends Exception implements I {
    }

    private static class Excep2 extends Exception implements I {
    }
}

Warum nicht Methode m2() kompilieren?

  • Welchen Kompilierungsfehler erhalten Sie?

    – Gawin

    9. Januar 2020 um 11:13 Uhr

Benutzer-Avatar
Eran

Der Typ des Ausdrucks

b ? new Excep1() : new Excep2()

ist Exceptionda dies der gemeinsame Obertyp von ist Excep1 und Excep2.

Sie fangen jedoch nicht Exceptionalso beschwert sich der Compiler darüber.

Wenn Sie fangen Exceptiones wird die Kompilierung bestehen:

public int m2(boolean b) {
    try {
        throw b ? new Excep1() : new Excep2();
    } catch (Exception e) {
        return 0;
    }
}

Ich habe versucht, den JLS-Eintrag zu finden, der die Art des bedingten ternären Ausdrucks in Ihrem Beispiel erklärt.

Alles, was ich finden konnte, war, dass dieser spezielle Ausdruck a ist 15.25.3. Referenzbedingter Ausdruck.

Ich bin mir nicht ganz sicher, ob es sich um einen Polyausdruck oder einen eigenständigen Ausdruck handelt. Ich denke, es ist eigenständig (da Poly-Ausdrücke einen Zuweisungskontext oder einen Aufrufkontext beinhalten, und ich denke nicht, dass a throw Aussage zählt als eines von beiden).

Für einen eigenständigen Ausdruck: “Wenn der zweite und dritte Operand denselben Typ haben (was der Nulltyp sein kann), dann ist das der Typ des bedingten Ausdrucks.”

In Ihrem Fall haben der zweite und dritte Operand drei gemeinsame Typen – Object, Throwable und Exception – Der Typ des Ausdrucks muss einer der letzten beiden sein, da “Der Ausdruck in einer throw-Anweisung entweder eine Variable oder einen Wert eines Referenztyps bezeichnen muss, der dem Typ Throwable zuweisbar ist (§5.2).”

Es scheint, dass der Compiler den spezifischsten allgemeinen Typ auswählt (Exception) und damit a catch (Exception e) behebt den Kompilierungsfehler.

Ich habe auch versucht, Ihre beiden benutzerdefinierten Ausnahmen durch zwei Unterklassen von zu ersetzen IOExceptionin welchem ​​Fall catch (IOException e) behebt den Kompilierungsfehler.

  • @Smile Der Typ des ternären Bedingungsausdrucks muss sowohl dem 2. als auch dem 3. Operanden gemeinsam sein. Daher kann es nicht sein Excep1 oder Excep2. Es kann nur sein Exception.

    – Eran

    9. Januar 2020 um 11:18 Uhr

  • Der letzte Aufzählungspunkt in 15.25.3 hat die Antwort: „Andernfalls sind der zweite und der dritte Operand vom Typ S1 bzw. S2. Sei T1 der Typ, der sich aus der Anwendung der Boxing-Konvertierung auf S1 ergibt, und sei T2 der Typ, der sich ergibt von der Anwendung der Boxing-Konvertierung auf S2. Der Typ des Bedingungsausdrucks ist das Ergebnis der Anwendung der Capture-Konvertierung (§5.1.10) auf lub(T1, T2).” lub hier ist Least Upper Bound, der nächste gemeinsame Supertyp, den die Typen der beiden Ausdrücke teilen.

    – Amalloy

    10. Januar 2020 um 21:32 Uhr

Benutzer-Avatar
GideonleGrange

Sie verwirren den Compiler mit dieser Zeile:

throw b ? new Excep1() : new Excep2();

Der Compiler sieht, dass das Ergebnis des Ausdrucks (rechts vom Throw) die gemeinsame Superklasse zwischen Except1 und Except2 ist, die Exception ist, und daher wird der effektive Typ, den Sie auslösen, zu Exception. Die catch-Anweisung kann nicht erkennen, dass Sie versuchen, Excep1 oder Except2 auszulösen.

Java beschränkt Sie darauf, alle Ausnahmetypen abzufangen oder zu deklarieren, die die Methode auslösen kann.

Es sucht nach gemeinsamen Eltern für beide (/all) Ausnahmen und erwartet, dass Sie abfangen oder als Throws deklarieren, zum Beispiel if Excep1 erweitert Throwable Sie müssen auch Throwable fangen

Im ersten Fall ist Java sicher, dass Sie entweder werfen Excep1 oder Excep2

1157970cookie-checkAbfangen mehrerer Ausnahmen in Java-8

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy