2016-09-27 10 views
25

확인 된 예외와 런타임 예외를 모두 throw 할 수있는 코드가 있습니다.확인 된 예외를 래핑하는 방법 Java에서 원래 런타임 예외를 유지하는 방법

확인 된 예외를 catch하고 런타임 예외로 감싸고 싶습니다. 하지만 RuntimeException이 던져지면 이미 런타임 예외이기 때문에 래핑 할 필요가 없습니다.

내가 가진 솔루션은 오버 헤드 비트를 가지고 있으며, "깔끔한"되지 않습니다 :

try { 
    // some code that can throw both checked and runtime exception 
} catch (RuntimeException e) { 
    throw e; 
} catch (Exception e) { 
    throw new RuntimeException(e); 
} 

어떤 생각이 더 우아한 방법을?

+5

합니다. 그 유일한 개선점은'try' 몸체 인 lambda를 받아들이고 그것을이 논리로 감싸는 고차 함수입니다. 이 주제를 확인할 수 있습니다 : http://stackoverflow.com/questions/31270759/a-better-approach-to-handling-exceptions-in-a-functionalway –

답변

26

확인 된 예외를 전달하기 위해 "blind"rethrow를 사용합니다. 나는이 예외를 체크 던진 lambdas를 사용할 수없는 Streams API를 통과하기 위해 이것을 사용했다. 예 : ThrowingXxxxx 기능 인터페이스가있어서 확인 된 예외를 전달할 수 있습니다.

이렇게하면 피 호출자가 확인 된 예외를 허용하지 않는 인터페이스를 통해 전달해야한다는 것을 알 필요없이 자연스럽게 호출 된 예외를 catch 할 수 있습니다.

try { 
    // some code that can throw both checked and runtime exception 

} catch (Exception e) { 
    throw rethrow(e); 
} 

확인 된 예외를 다시 선언 할 수 있습니다.

public void loadFile(String file) throws IOException { 
    // call method with rethrow 
} 

/** 
* Cast a CheckedException as an unchecked one. 
* 
* @param throwable to cast 
* @param <T>  the type of the Throwable 
* @return this method will never return a Throwable instance, it will just throw it. 
* @throws T the throwable as an unchecked throwable 
*/ 
@SuppressWarnings("unchecked") 
public static <T extends Throwable> RuntimeException rethrow(Throwable throwable) throws T { 
    throw (T) throwable; // rely on vacuous cast 
} 

예외를 처리하기위한 다른 선택의 여지가있다

. 우리는 그것들 중 몇 가지를 사용합니다.

https://vanilla-java.github.io/2016/06/21/Reviewing-Exception-Handling.html

+2

그래서 런타임에 IOException ('rethrow'에서)을 던졌습니다.하지만 컴파일러는 체크되지 않은 예외라고 생각합니다 (캐스트가 지워지더라도 그것을 캐스팅한다고 말했기 때문에)? – Thilo

+2

@Thilo 런타임에는 JVM에 대해 선택 항목과 선택 항목간에 차이가 없으며 런타임에 작동하는 컴파일러를 "속일"수있는 몇 가지 방법이 있습니다. 제네릭을 사용하는 캐스트는 내가 느끼는 가장 단순한 것입니다. –

+1

부적절합니다. 나는 그것을 좋아한다. :-) (예, lamdbas의 예외는 불편하지 않습니다.) – Thilo

5

아니요.

이 작업을 많이 수행하면 도우미 방법으로 옮길 수 있습니다.

static RuntimeException unchecked(Throwable t){ 
    if (t instanceof RuntimeException){ 
     return (RuntimeException) t; 
    } else if (t instanceof Error) { // if you don't want to wrap those 
     throw (Error) t; 
    } else { 
     return new RuntimeException(t); 
    } 
} 

try{ 
// .. 
} 
catch (Exception e){ 
    throw unchecked(e); 
} 
+0

'catch (Exception e)'를'catch (Throwable e)'? –

+0

@ JasonS :'Error' (권장하지 않음)를 잡으려는 경우 가능합니다. 나는 그걸 잡히지 않게 할 뿐이야. 컴파일러는 그것에 대해 불평하지 않을 것입니다. – Thilo

+0

필자는 'Throwable'을 사용할 이유가 없다고 생각하고 'Exception'만 잡으면 'Error'에 대한 특별한 경우가 있다고 생각합니다. – OrangeDog

1

당신은

try { 
    // some code that can throw both checked and runtime exception 
} catch (Exception e) { 
    if (e instanceof RuntimeException) { 
     throw e; 
    } else { 
     throw new RuntimeException(e); 
    } 
} 

그러나, 솔루션이 좋아 보이는 운영자

을 instanceof를 사용하여 동일한을 다시 작성할 수 있습니다.

16

구아바의 Throwables.propagate()는 않습니다 정확히 :

try { 
    // some code that can throw both checked and runtime exception 
} catch (Exception e) { 
    throw Throwables.propagate(e); 
} 

UPDATE :이 방법은 현재 사용되지 않습니다. 자세한 설명은 this page을 참조하십시오.

+0

무관계 : 오늘 나는 전설적인 금을 얻고 싶다 ... 모든 사람들에게 감사하다는 말을 전부터 많이 배웠다 ... – GhostCat

1

문제는 Exception이 너무 광범위하다는 것입니다. 가능한 체크 예외가 무엇인지 정확히 알아야합니다.

try { 
    // code that throws checked and unchecked exceptions 
} catch (IOException | SomeOtherException ex) { 
    throw new RuntimeException(ex); 
} 

이 대신 해결해야 더 깊은 문제 공개 작동하지 않을 이유 : 방법이 throws Exception 그때는 너무 광범위되고 있음을 선언하는 경우

가. 더 이상 정보가없는 "무언가 잘못 될 수 있음"을 알고있는 것은 발신자에게 유용하지 않습니다. 메소드는 의미있는 계층 구조의 특정 예외 클래스를 사용하거나 적절한 경우 검사되지 않은 예외를 사용해야합니다.

메서드가 너무 많은 종류의 확인 된 예외를 throw하면 너무 복잡합니다. 여러 가지 간단한 방법으로 리팩터링하거나 상황에 따라 예외를 합리적인 상속 계층 구조로 배열해야합니다.

물론 예외가있을 수 있습니다. 메소드 throws Exception을 선언하는 것은 다른 사람들이 사용할 수 있도록 API를 구성하기보다는 일종의 크로스 커팅 프레임 워크 (예 : JUnit 또는 AspectJ 또는 Spring)에 의해 소비되는 경우 완벽하게 합리적 일 수 있습니다.

+1

그의 방법은 예외를 던지라고 선언하지 않는다. 그는 뭔가 더 우아하게 붙잡고 싶다. 호출 스택을 내리면 예외가 발생합니다. 여기에는 직접 호출하는 메서드에서 선언 한 형식화 된 예외 또는 NPE 또는 기타 잘못 될 수있는 예외가 포함될 수 있습니다. 완벽하게 합리적인. – user467257

+0

@ user467257 예 OP를 이해합니다. 'try'd 코드가'Exception'을 throw하는 메소드 인 경우 제안 된 패턴이 작동하지 않을 것이라고 지적하고 있습니다.하지만이 메소드는 잘못 설계된 것입니다. – OrangeDog

1

나는 일반적으로 코드 구조의 동일한 유형을 사용하지만, 몇 번 중 하나에 한 줄에 아래로 응축 삼항 연산자는 실제로 더 나은 코드합니다 :

try { 
    // code that can throw 
} 
catch (Exception e) { 
    throw (e instanceof RuntimeException) ? (RuntimeException) e : new RuntimeException(e); 
} 

이 필요로하지 않는 추가 방법이나 catch을 블록이 내가 좋아하는 이유입니다.

3

나는 다음을 포함하는 특별히 컴파일 된 .class 파일이 : 그것은 단지 작동

public class Thrower { 
    public static void Throw(java.lang.Throwable t) { 
     throw t; 
    } 
} 

합니다. Java 컴파일러는 일반적으로 이것을 컴파일하는 것을 거부하지만, 바이트 코드 검증자는 전혀 신경 쓰지 않습니다.

클래스

피터 Lawrey의 대답과 유사한 사용 : 그거야

try { 
    // some code that can throw both checked and runtime exception 

} catch (Exception e) { 
    Thrower.Throw(e); 
} 
+5

어떻게 컴파일 했습니까? – shmosel

+2

javac 소스 코드를 편집하여 체크 아웃 한 다음 javac을 컴파일하고 javac를 사용하여 .class 파일을 컴파일했습니다. 생성 된 .class 파일은 일반적인 javac에 의해 컴파일 된 .java 컴파일 파일에 의해 참조 될 수 있습니다. – Joshua

+0

와우, 내가 기대했던 것이 아닙니다. 파일을 어딘가에 사용할 수 있습니까? – shmosel