Java-8에서 여러 예외 잡기


71

멀티 캐치 기능을 시험해 보면서 내 m1()방법에서 모든 것이 예상대로 잘 작동합니다.

그러나 m2()동일한 코드 에서 컴파일되지 않습니다. 코드 줄 수를 줄이기 위해 구문을 변경했습니다.

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

왜 메소드가 m2()컴파일 되지 않습니까?


22
어떤 컴파일 오류가 발생합니까?
개빈

답변:


79

식의 유형

b ? new Excep1() : new Excep2()

이다 Exception그의 공통의 슈퍼 타입이기 때문에, Excep1하고 Excep2.

그러나, 당신은 잡고 있지 않으므로 Exception컴파일러가 그것에 대해 불평합니다.

catch하면 Exception컴파일을 전달합니다.

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

귀하의 예에서 조건부 삼항 식의 유형을 설명하는 JLS 항목을 찾으려고했습니다.

내가 찾을 수있는 것은이 특정 표현이 15.25.3이라는 것입니다. 참조 조건식 .

그것이 폴리 식 또는 독립 식으로 계산되는지 확실하지 않습니다. 나는 그것이 독립형이라고 생각합니다 (폴리 표현식에는 할당 컨텍스트 또는 호출 컨텍스트가 포함되므로 throw명령문이 그중 하나 라고 생각하지 않기 때문에 ).

독립형 표현식의 경우 : "두 번째 및 세 번째 피연산자가 동일한 유형 (널 유형일 수 있음)을 갖는 경우 이는 조건식 유형입니다."

귀하의 경우에는, 두 번째와 세 번째 피연산자는 세 가지 일반적인 유형이 - Object, ThrowableException- throw 문의 표현 중 하나를 참조 형식의 변수 또는 값을 표시해야한다 ", 이후 표현의 유형, 후자의 두 가지 중 하나 여야합니다 이는 Throwable 유형에 지정할 수 있습니다 (§5.2). "

컴파일러는 가장 구체적인 공통 유형 ( Exception)을 선택하므로 catch (Exception e)컴파일 오류를 해결합니다.

또한 두 개의 하위 클래스로 두 개의 사용자 정의 예외를 대체하기 위해 노력 IOException하는 경우가있는, catch (IOException e)컴파일 에러를 해결한다.


11
@Smile 삼항 조건식의 유형은 두 번째 및 세 번째 피연산자 모두에 공통이어야합니다. 따라서 Excep1또는 일 수 없습니다 Excep2. 만 가능합니다 Exception.
Eran

2
15.25.3의 마지막 글 머리 기호는 "그렇지 않으면 두 번째와 세 번째 피연산자는 각각 S1과 S2 유형입니다. T1은 S1에 권투 변환을 적용한 결과이고 T2는 결과 유형입니다. 조건식의 유형은 캡처 변환 (§5.1.10)을 lub (T1, T2)에 적용한 결과입니다. " 여기에 lub은 Least Upper Bound로, 두 표현식 유형이 공유하는 가장 가까운 공통 수퍼 타입입니다.
amalloy

22

컴파일러를 다음 줄과 혼동하고 있습니다.

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

컴파일러는 예외의 왼쪽에있는 표현식의 결과가 예외 인 Except1과 Except2 사이의 공통 수퍼 클래스이므로 예외 유형이 예외임을 알게됩니다. catch 문은 Excep1 또는 Except2를 던지려고한다는 것을 알 수 없습니다.


4

Java는 메소드가 던질 수있는 모든 예외 유형을 포착하거나 선언하도록 제한합니다.

그것은 (/ 모두) 모두에 대해 공통의 부모에 대한 예외를 검색하고있는 경우, 예를 들어, 던져 당신이 잡을 또는 선언 할 것으로 예상 Excep1확장 Throwable당신은 또한의 Throwable을 잡으려고해야합니다

첫 번째 경우 Java는 던지 Excep1거나Excep2

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.