Capturando Várias Exceções no Java-8


71

Ao experimentar o recurso de captura múltipla, encontrei no meu m1()método que tudo está funcionando bem como esperado.

No entanto, no m2()mesmo código não compila. Acabei de alterar a sintaxe para reduzir o número de linhas de código.

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

Por que o método não m2()compila?


22
Que erro de compilação você está recebendo?
Gavin

Respostas:


79

O tipo da expressão

b ? new Excep1() : new Excep2()

é Exception, já que esse é o supertipo comum de Excep1e Excep2.

No entanto, você não está entendendo Exception, então o compilador reclama disso.

Se você pegar Exception, ele passará a compilação:

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

Tentei encontrar a entrada JLS que explica o tipo de expressão ternária condicional no seu exemplo.

Tudo o que pude encontrar foi que essa expressão em particular é uma 15.25.3. Expressão Condicional de Referência .

Não tenho muita certeza se isso conta como expressão poli ou expressão independente. Eu acho que é autônomo (uma vez que as expressões polifônicas envolvem um contexto de atribuição ou de invocação, e não acho que uma throwdeclaração seja considerada uma dessas).

Para uma expressão autônoma: "Se o segundo e o terceiro operando tiverem o mesmo tipo (que pode ser o tipo nulo), esse é o tipo da expressão condicional."

No seu caso, o segundo e operandos terceiros têm três tipos comuns - Object, Throwablee Exception- o tipo de expressão deve ser um dos dois últimos, uma vez que, "A expressão em uma instrução throw ou deve denotar uma variável ou o valor de um tipo de referência que é atribuível (§5.2) ao tipo Throwable ".

Parece que o compilador escolhe o tipo comum mais específico ( Exception) e, portanto, catch (Exception e)resolve o erro de compilação.

Também tentei substituir suas duas exceções personalizadas por duas subclasses de IOException, nesse caso, catch (IOException e)resolve o erro de compilação.


11
@ Sorria, o tipo da expressão condicional ternária deve ser comum aos 2º e 3º operandos. Portanto, não pode ser Excep1ou Excep2. Só pode ser Exception.
Eran

2
O ponto final em 15.25.3 tem a resposta: "Caso contrário, o segundo e o terceiro operandos são do tipo S1 e S2, respectivamente. Seja T1 o tipo que resulta da aplicação da conversão de boxe em S1 e T2 seja o tipo que resulta de aplicar a conversão de boxe para S2. O tipo da expressão condicional é o resultado da aplicação da conversão de captura (§5.1.10) em lub (T1, T2). " lub aqui é Menor limite superior, que é o supertipo comum mais próximo que os tipos das duas expressões compartilham.
amalloy 10/01

22

Você está confundindo o compilador com esta linha:

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

O compilador vê que o resultado da expressão (à esquerda do arremesso) é a superclasse comum entre Except1 e Except2, que é Exception, e, portanto, o tipo efetivo que você está lançando se torna Exception. Não é possível pegar a instrução catch que você está tentando lançar Excep1 ou Except2.


4

Java restringe você a capturar ou declarar todos os tipos de exceção que o método pode lançar,

Ele procura por pai comum para ambas as exceções (/ todas) e espera que você capture ou declare como arremessos, por exemplo, se Excep1estenderThrowable você também precisará capturar Throwable

No primeiro caso, Java tem certeza de que está jogando Excep1ouExcep2

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.