Cattura di più eccezioni in Java-8


71

Mentre provavo la funzione multi-catch ho trovato nel mio m1()metodo che tutto funziona come previsto.

Tuttavia, nello m2()stesso codice non viene compilato. Ho appena cambiato la sintassi per ridurre il numero di righe di codice.

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 {
    }
}

Perché il metodo non si m2()compila?


22
Che errore di compilazione stai ricevendo?
Gavin,

Risposte:


79

Il tipo di espressione

b ? new Excep1() : new Excep2()

è Exception, poiché questo è il supertipo comune di Excep1e Excep2.

Tuttavia, non stai catturando Exception, quindi il compilatore si lamenta.

Se catturi Exception, passerà la compilazione:

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

Ho provato a trovare la voce JLS che spiega il tipo di espressione ternaria condizionale nel tuo esempio.

Tutto quello che ho potuto trovare è che questa particolare espressione è un 15.25.3. Espressione condizionale di riferimento .

Non sono del tutto sicuro se conta come un'espressione poli o un'espressione autonoma. Penso che sia autonomo (dal momento che le espressioni poli coinvolgono un contesto di assegnazione o un contesto di invocazione e non credo che throwun'istruzione contenga come una di queste).

Per un'espressione autonoma: "Se il secondo e il terzo operando hanno lo stesso tipo (che può essere il tipo null), questo è il tipo dell'espressione condizionale."

Nel suo caso, il secondo e operandi terzi hanno tre tipi comuni - Object, Throwablee Exception- il tipo di espressione deve essere uno di questi ultimi due, poiché "L'espressione in un'istruzione throw deve o denotare una variabile o un valore di un tipo di riferimento che è assegnabile (§5.2) al tipo gettabile. "

Sembra che il compilatore scelga il tipo comune più specifico ( Exception), e quindi catch (Exception e)risolve l'errore di compilazione.

Ho anche provato a sostituire le tue due eccezioni personalizzate con due sottoclassi di IOException, nel qual caso catch (IOException e)risolve l'errore di compilazione.


11
@Smile il tipo dell'espressione condizionale ternaria deve essere comune sia al 2 ° che al 3 ° operando. Pertanto non può essere Excep1o Excep2. Può solo essere Exception.
Eran,

2
Il punto elenco finale in 15.25.3 ha la risposta: "Altrimenti, il secondo e il terzo operando sono rispettivamente dei tipi S1 e S2. Sia T1 il tipo che risulta dall'applicazione della conversione di boxe in S1 e T2 sia il tipo che risulta dall'applicazione della conversione di boxe a S2. Il tipo dell'espressione condizionale è il risultato dell'applicazione della conversione di cattura (§5.1.10) a lub (T1, T2). " lub qui è Least Upper Bound, che è il supertipo comune più vicino condiviso dai tipi di due espressioni.
amalloy,

22

Stai confondendo il compilatore con questa riga:

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

Il compilatore vede che il risultato dell'espressione (a sinistra del lancio) è la superclasse comune tra Except1 ed Except2, che è Eccezione, e quindi il tipo effettivo che stai lanciando diventa Eccezione. L'istruzione catch non rileva che stai tentando di lanciare Excep1 o Except2.


4

Java ti limita a catturare o dichiarare tutti i tipi di eccezione che il metodo può generare,

E 'la ricerca di genitore comune per entrambi (/ tutti) Eccezioni e si aspettano a catturare o dichiarare come butta, per esempio se Excep1si estende Throwablesi dovrà prendere anche Throwable

Nel primo caso Java è sicuro che stai lanciando Excep1oExcep2

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.