동일한 catch 절에서 여러 Java 예외를 포착 할 수 있습니까?


699

Java에서는 다음과 같이하고 싶습니다.

try {
    ...     
} catch (/* code to catch IllegalArgumentException, SecurityException, 
            IllegalAccessException, and NoSuchFieldException at the same time */) {
   someCode();
}

...대신에:

try {
    ...     
} catch (IllegalArgumentException e) {
    someCode();
} catch (SecurityException e) {
    someCode();
} catch (IllegalAccessException e) {
    someCode();
} catch (NoSuchFieldException e) {
    someCode();
}

이것을 할 수있는 방법이 있습니까?

답변:


1131

이것은 Java 7부터 가능했습니다 . 멀티 캐치 블록의 구문은 다음과 같습니다.

try { 
  ...
} catch (IOException | SQLException ex) { 
  ...
}

그러나 모든 예외가 동일한 클래스 계층 구조에 속하는 경우 해당 기본 예외 유형을 간단히 잡을 수 있습니다.

또한 ExceptionB가 ExceptionA에서 직접 또는 간접적으로 상속되는 경우 동일한 블록에서 ExceptionA와 ExceptionB를 모두 잡을 수 없습니다. 컴파일러는 다음과 같이 불평합니다.

Alternatives in a multi-catch statement cannot be related by subclassing
  Alternative ExceptionB is a subclass of alternative ExceptionA

81
TT - 왜 재정의 bitwise or( |) 연산자를? 쉼표 또는 더 유사한 의미를 가진 연산자 logical or( ||)를 사용하지 않겠습니까?
ArtOfWarfare

11
@ArtOfWarfare 어쩌면 그들은 제네릭에 대한 다중 경계 구문을 이미 생각 해낸 후에는 더 이상 중요하지 않을 것이라고 생각했을 것 입니다.
JimmyB

12
XOR 부호 (I)는 OR (||), A | B는 A 또는 B를 의미 하지만 A || B는 예외가 예외 A 또는 예외 B이지만 동시에 둘 다가 아닌 A 또는 B 또는 둘 다를 의미합니다. 그들은 XOR 대신 노래 또는 사용하고 당신이 그들 중 하나가 다른의 하위 유형이 개 예외를 넣어 경우가 발생하면 예외는 당신이 명확하게 볼 수있는 이유입니다
user1512999

41
@ user1512999 Java에서 비트 XOR은 ^ (캐럿)이고 비트 OR은 | (pipe) docs.oracle.com/javase/tutorial/java/nutsandbolts/op3.html
Lewis Baumstark

6
다중 catch 블록에서 잡은 예외의 유형은 대부분의 파생 일반적인 부모에게 evalueted 것을 언급 그것의 가치는
yanpas

104

Java 7 이전에는 아니지만 다음과 같이 할 것입니다.

자바 6 이전

try {
  //.....
} catch (Exception exc) {
  if (exc instanceof IllegalArgumentException || exc instanceof SecurityException || 
     exc instanceof IllegalAccessException || exc instanceof NoSuchFieldException ) {

     someCode();

  } else if (exc instanceof RuntimeException) {
     throw (RuntimeException) exc;     

  } else {
    throw new RuntimeException(exc);
  }

}



자바 7

try {
  //.....
} catch ( IllegalArgumentException | SecurityException |
         IllegalAccessException |NoSuchFieldException exc) {
  someCode();
}

11
Java 6 예제는 컴파일러가 어디에서 무엇이 발생하는지 알려주는 기능을 깨뜨립니다.
MichaelBlume

2
@MichaelBlume True는 나쁘지 않습니다. 로 원래 예외를 항상 얻을 수 있습니다 exc.getCause(). 부수적으로, Robert C. Martin (다른 것들 중에서도)은 확인되지 않은 예외를 사용하도록 권장합니다 (컴파일러는 어떤 예외가 발생하는지 알 수 없습니다). 7 장 : 자신의 저서에있는 오류 처리 Clean code를 참조하십시오 .
user454322

4
자바 6 예에서 당신은 즉, 원래의 예외를 rethrowing 대신 새로운 예외 인스턴스를 생성하지 않아야 throw exc대신 throw new RuntimeException(exc)?
David DeMar

5
가독성 측면에서 볼 때 이것은 매우 나쁜 습관입니다.
Rajesh J Advani

3
Instanceof 작업은 약간 비용이 많이들므로 최대한 피하는 것이 좋습니다.
Paramesh Korrakuti

23

Java 7 내에서 다음과 같은 여러 catch 절을 정의 할 수 있습니다.

catch (IllegalArgumentException | SecurityException e)
{
    ...
}

16

예외 계층 구조가있는 경우 기본 클래스를 사용하여 모든 하위 클래스 예외를 포착 할 수 있습니다. 축약 된 경우 다음을 사용하여 모든 Java 예외를 포착 할 수 있습니다 .

try {
   ...
} catch (Exception e) {
   someCode();
}

보다 일반적인 경우에 RepositoryException이 기본 클래스이고 PathNotFoundException이 파생 클래스 인 경우 :

try {
   ...
} catch (RepositoryException re) {
   someCode();
} catch (Exception e) {
   someCode();
}

위의 코드는 한 종류의 예외 처리에 대해 RepositoryException 및 PathNotFoundException을 포착하며 다른 모든 예외는 함께 일괄 처리됩니다. Java 7부터 위의 @OscarRyz의 답변에 따라 :

try { 
  ...
} catch( IOException | SQLException ex ) { 
  ...
}

7
BTW catch 절은 순서대로 처리되므로 부모 클래스를 자식 클래스 앞에 놓으면 호출되지 않습니다. 예 : try {...} catch (Exception e) {someCode (); } catch (RepositoryException re) {// 결코 도달하지 않음}
Michael Shopsin

4
실제로 정확하게 도달 할 수 없기 때문에 그러한 코드는 컴파일되지 않습니다.
polygenelubricants

15

아니요, 고객 당 하나입니다.

모든 경우에 동일한 조치를 취하는 한 java.lang.Exception과 같은 수퍼 클래스를 잡을 수 있습니다.

try {
    // some code
} catch(Exception e) { //All exceptions are caught here as all are inheriting java.lang.Exception
    e.printStackTrace();
}

그러나 이것이 최선의 방법이 아닐 수도 있습니다. 실제로 처리하기위한 전략이있는 경우에만 예외를 잡아야합니다. 로깅 및 재 투입은 "처리"가 아닙니다. 수정 조치가없는 경우 메소드 서명에 추가하고 상황을 처리 할 수있는 누군가에게 버블 링하도록하십시오.


20
java.lang.Exception을 잡는 것에 대한 부분을 다시 말씀해 주시겠습니까? 나는 그것이 예일 뿐이라는 것을 알고 있지만, 어떤 사람들은이 대답을 읽고 "아, 그래, 그때 예외를 잡을 것"이라고 생각할 것입니다.
Rob Hruska

2
나는 그것에 대해 알고 있었지만 그것을하고 싶지 않다 ... 오, 음, 다음 버전의 자바가 나올 때까지 4 개의 어획량에 갇힌 것 같다.
froadie

@ duffymo : 로깅 및 다시 던지기에 어떤 문제가 있습니까? 코드를 어지럽히는 것을 제외하고는 코드를 잡지 않는 것과 같습니다. 일반적인 오류 처리 전략 관점에서 볼 수 있습니다. 나쁜 점은 로깅하고 다시 던지지 않는 것 입니다.
Frank Osterfeld

5
로깅을 처리하고 다시 처리하는 것을 고려하지 않습니다. 의미있는 일을 할 수있는 사람에게 말을 걸고 싶습니다. 예외를 피해야하는 마지막 계층 (예 : 웹앱의 컨트롤러)은이 경우 오류를 기록하는 계층이어야합니다.
duffymo

나는 로그가 자동으로 생성되지 않는다는 것을 부끄럽게 생각하는 유일한 사람입니까? 일부 코드에서 예외가 발생할 때마다 모두 동일한 바보 로깅 메시지를 작성해야합니다.
ArtOfWarfare

10

Java 6 (즉, Android)에 대한 user454322의 답변에 대한 깔끔하지만 덜 장황하고 바람직하지는 않은 대안은 모든 것을 잡고 Exception다시 던질 것 RuntimeException입니다. 이 것없는 작품 만약 당신이있는 거 (당신은 또한하지 않는 한 그들을 다시 던져) 더 스택까지 예외의 다른 유형을 잡기에 계획, 그러나 효과적으로 모든 잡을 것 확인 예외.

예를 들어 :

try {
    // CODE THAT THROWS EXCEPTION
} catch (Exception e) {
    if (e instanceof RuntimeException) {
        // this exception was not expected, so re-throw it
        throw e;
    } else {
        // YOUR CODE FOR ALL CHECKED EXCEPTIONS
    } 
}

즉, 자세한 내용은 부울 또는 다른 변수를 설정하고 try-catch 블록 다음에 일부 코드를 실행하는 것이 가장 좋습니다.


1
이 접근법은 컴파일러가 "캐치 블록"에 도달 할 수 있는지 여부를 판별하지 못하게합니다.
the_new_mr

3

7 이전의 방법은 다음과 같습니다.

  Boolean   caught = true;
  Exception e;
  try {
     ...
     caught = false;
  } catch (TransformerException te) {
     e = te;
  } catch (SocketException se) {
     e = se;
  } catch (IOException ie) {
     e = ie;
  }
  if (caught) {
     someCode(); // You can reference Exception e here.
  }

3
wuold는 좋은 해결책이 될 것입니다. 블록 caught에 최종 제어를 삽입하는 것은 finally어떻습니까?
Andrea_86

원래 질문보다 더 많은 줄이 필요합니다.
Leandro Glossman

1

예. pipe (|) 구분 기호를 사용하는 방법은 다음과 같습니다.

try
{
    .......
}    
catch
{
    catch(IllegalArgumentException | SecurityException | IllegalAccessException | NoSuchFieldException e)
}

이 코드 스타일은 무엇입니까? catch 블록을 try 블록으로?
Sam

1

kotlin의 경우 현재로서는 불가능하지만 그것을 추가하는 것을 고려했습니다 : Source
그러나 지금은 약간의 트릭입니다.

try {
    // code
} catch(ex:Exception) {
    when(ex) {
        is SomeException,
        is AnotherException -> {
            // handle
        }
        else -> throw ex
    }
}

0

예외 계층 구조에서 상위 클래스가되는 예외를 포착하십시오. 이것은 물론 나쁜 습관 입니다. 귀하의 경우 공통 부모 예외는 예외 클래스이며 예외 인스턴스 인 예외를 포착하는 것은 실제로 나쁜 습관입니다. NullPointerException과 같은 예외는 일반적으로 프로그래밍 오류이며 일반적으로 null 값을 확인하여 해결해야합니다.

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