Beim Ausprobieren der Multi-Catch- Funktion habe ich in meinem gefundenm1()
Methode , funktioniert alles wie erwartet.
Im m2()
selben Code wird jedoch nicht kompiliert. Ich habe gerade 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 m2()
kompiliert die Methode nicht ?
Antworten:
Die Art des Ausdrucks
ist
Exception
, da dies der übliche Supertyp vonExcep1
und istExcep2
.Da Sie jedoch nicht fangen
Exception
, beschwert sich der Compiler darüber.Wenn Sie fangen
Exception
, wird es die Kompilierung bestehen:Ich habe versucht, den JLS-Eintrag zu finden, der die Art des bedingten ternären Ausdrucks in Ihrem Beispiel erklärt.
Ich konnte nur feststellen, dass dieser spezielle Ausdruck ein 15.25.3 ist. 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
Anweisung als zählt).Für einen eigenständigen Ausdruck: "Wenn der zweite und der dritte Operand denselben Typ haben (der möglicherweise der Nulltyp ist), ist dies der Typ des bedingten Ausdrucks."
In Ihrem Fall haben die zweite und dritte Operanden drei Arten -
Object
,Throwable
undException
- die Art des Ausdrucks einer der beiden letzteren sein muß, da „Der Ausdruck in einer throw - Anweisung entweder eine Variable oder Wert eines Referenztypen bezeichnen muss welches dem Typ Throwable zuweisbar ist (§5.2). "Es scheint, dass der Compiler den spezifischsten allgemeinen Typ (
Exception
)catch (Exception e)
auswählt und daher den Kompilierungsfehler löst.Ich habe auch versucht, Ihre beiden benutzerdefinierten Ausnahmen durch zwei Unterklassen von zu ersetzen.
IOException
In diesem Fall wirdcatch (IOException e)
der Kompilierungsfehler behoben.quelle
Excep1
oderExcep2
. Es kann nur seinException
.Sie verwechseln den Compiler mit dieser Zeile:
Der Compiler sieht, dass das Ergebnis des Ausdrucks (links vom Wurf) die gemeinsame Superklasse zwischen Except1 und Except2 ist, bei der es sich um Exception handelt. Daher wird der effektive Typ, den Sie auslösen, zu Exception. Die catch-Anweisung kann nicht erkennen, dass Sie versuchen, Excep1 oder Except2 zu werfen.
quelle
Java beschränkt Sie darauf, alle Ausnahmetypen abzufangen oder zu deklarieren, die diese Methode auslösen kann.
Es sucht nach einem gemeinsamen Elternteil für beide (/ alle) Ausnahmen und erwartet, dass Sie Würfe fangen oder als Würfe deklarieren. Wenn Sie beispielsweise
Excep1
verlängern, müssenThrowable
Sie auch Throwable fangenIm ersten Fall ist Java sicher, dass Sie entweder werfen
Excep1
oderExcep2
quelle