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?
Respostas:
O tipo da expressão
é
Exception
, já que esse é o supertipo comum deExcep1
eExcep2
.No entanto, você não está entendendo
Exception
, então o compilador reclama disso.Se você pegar
Exception
, ele passará a compilação: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
throw
declaraçã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
,Throwable
eException
- 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.fonte
Excep1
ouExcep2
. Só pode serException
.Você está confundindo o compilador com esta linha:
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.
fonte
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
Excep1
estenderThrowable
você também precisará capturar ThrowableNo primeiro caso, Java tem certeza de que está jogando
Excep1
ouExcep2
fonte