throws 선언을 추가하지 않고 예외를 throw하는 방법이 있습니까?


81

나는 다음과 같은 상황이 있습니다.

다른 기본 클래스에서 상속하고 메서드를 재정의하는 Java 클래스가 있습니다. 기본 메서드는 예외를 throw하지 않으므로 throws ...선언 이 없습니다 .

이제 내 자신의 방법이 예외를 throw 할 수 있어야하지만 선택권이 있습니다.

  • 예외를 삼켜 라
  • throws 선언 추가

첫 번째는 예외를 자동으로 무시하고 (몇 가지 로깅을 수행 할 수 있음) 두 번째는 다른 메서드 헤더로 인해 컴파일러 오류를 생성하므로 둘 다 만족스럽지 않습니다.

public class ChildClass extends BaseClass {

        @Override 
        public void SomeMethod() {
            throw new Exception("Something went wrong");
        }
}

답변:


99

정말로 원한다면 선언하지 않고도 확인되지 않은 예외를 던질 수 있습니다. 확인되지 않은 예외는 RuntimeException. 확장 Error되는 Throwables 도 확인되지 않지만 완전히 처리 할 수없는 문제 (예 : 유효하지 않은 바이트 코드 또는 메모리 부족)에만 사용해야합니다.

특정 경우에 Java 8 UncheckedIOException은 래핑 및 다시 던지기를 위해 추가되었습니다 IOException.


1
훌륭하게 작동합니다. 예외가 다른 메서드에서 발생하기 때문에 RuntimeException을 다시 던져야하지만 훌륭하게 작동합니다. 감사합니다.
Jürgen Steinblock 2010

42

다음은 트릭입니다.

class Utils
{
    @SuppressWarnings("unchecked")
    private static <T extends Throwable> void throwException(Throwable exception, Object dummy) throws T
    {
        throw (T) exception;
    }

    public static void throwException(Throwable exception)
    {
        Utils.<RuntimeException>throwException(exception, null);
    }
}

public class Test
{
    public static void main(String[] args)
    {
        Utils.throwException(new Exception("This is an exception!"));
    }
}

어떻게 작동하는지 궁금합니다. 조사를 좀 해보 겠지만 저에게 도움이 될만한 자료가 있습니까? :-)
holmicz 2016

T는 RuntimeException으로 추론됩니다. 여기에 답변 됨 stackoverflow.com/questions/41380656/… 그리고 여기 stackoverflow.com/questions/31316581/…
seenimurugan

1
멋진 트릭! 이 트릭은 람다 식 / 블록에도 적용하여 throws선언 없이 SAM 인터페이스에 검사 된 예외 메서드를 할당 할 수 있습니다.
JasonMing

안전하지 않은 상황을 처리 할 필요가 없다는 추가 슈퍼 추가 보너스가 있습니다.
lscoughlin

더미 매개 변수가 필요한 이유는 무엇입니까? 또한 일반적인 방법 없이도 작동 할 수 있습니까?
Kiruahxh 2010 년

28

세 번째 옵션은 예외 검사를 옵트 아웃하고 (표준 API 자체가 가끔 수행해야하는 것처럼) 확인 된 예외를 다음과 같이 래핑하는 것입니다 RuntimeException.

throw new RuntimeException(originalException);

보다 구체적인 하위 클래스를 사용할 수 있습니다 RuntimeException.


10

순전히 FYI 로 대체 답변을 추가하고 싶습니다. .

예, 클래스 throws를 사용하여 선언 을 추가하지 않고 확인 된 예외를 throw하는 방법이 sun.misc.Unsafe있습니다. 이는 다음 블로그 게시물에 설명되어 있습니다.

선언하지 않고 메서드에서 확인 된 예외를 throw합니다.

샘플 코드 :

public void someMethod() {
  //throw a checked exception without adding a "throws"
  getUnsafe().throwException(new IOException());
}

private Unsafe getUnsafe() {
  try {
    Field field = Unsafe.class.getDeclaredField("theUnsafe");
    field.setAccessible(true);
    return (Unsafe) field.get(null);
  } catch (Exception e) {
    throw new RuntimeException(e);
  }
}

그러나 이것은 권장되지 않습니다. 다른 답변 중 일부에 설명 된대로 확인되지 않은 예외로 래핑하는 것이 좋습니다.


3
그들이 그 클래스를 부르는 이유가 있습니다 Unsafe.
OrangeDog 2010

4

확인되지 않은 예외를 던지지 않는 이유는 무엇입니까? 이것은 선언 할 필요가 없습니다.

두 가지 대안은

  • 확인되지 않은 예외로 확인 된 예외로 래핑합니다.
  • 컴파일러에게 확인 된 예외를 던지고 있음을 알리지 마십시오. 예 : Thread.currentThread (). stop (e);
  • Java 6에서는 예외가 발생한 경우 다시 throw 할 수 있습니다. final 있으며 컴파일러는 어떤 확인 된 예외를 포착했는지 알고 있습니다.
  • Java 7에서 예외가 사실상 최종적인 경우, 즉 코드에서 변경하지 않으면 예외를 다시 던질 수 있습니다.

나중에 코드에서 검사 예외를 발생시키고 호출 코드에서이를 포착 할 때 더 유용하지만 그 사이의 계층은 예외에 대해 아무것도 알지 못합니다.


두 번째 방법도 흥미 롭습니다. 그러나 현재로서는 예외를 래핑하는 것이 정확히 필요한 것입니다.
Jürgen Steinblock 2010


@OrangeDog, 당신이 이것을 읽었으므로 현재 스레드에서 stop ()을 사용하는 것과 래핑 된 예외를 던지는 것의 차이점이 무엇인지 말해 줄 수 있습니다. ;)
Peter Lawrey 2010

"다음 메서드는 Java의 throw 작업과 동작 적으로 동일하지만 호출 메서드가 throw 할 수있는 모든 검사 된 예외를 선언했는지 확인하려는 컴파일러의 시도를 피합니다."예외를 래핑하는 것이 더 나은 방법입니까?
Peter Lawrey 2010

"스레드를 중지하면 잠긴 모든 모니터의 잠금이 해제됩니다. 이전에 이러한 모니터에 의해 보호 된 개체가 일관성없는 상태에있는 경우 다른 스레드는 이제 이러한 개체를 일관성없는 상태로 볼 수 있습니다. [...] 달리 기타 확인되지 않은 예외 [...] 사용자는 자신의 프로그램이 손상 될 수 있다는 경고가 없습니다. "
OrangeDog 2010

4

예, 이유가 있지만 전혀 사용하지 않는 것이 좋습니다.

자바 안전하지 않은 패키지

getUnsafe().throwException(new IOException());

이 메서드는 확인 된 예외를 throw하지만 코드에서이를 포착하거나 다시 throw하지 않습니다. 런타임 예외와 같습니다.


2

다음은 확인 된 예외를 가로 채서 확인되지 않은 예외로 래핑하는 예입니다.

public void someMethod() {
   try {
      doEvil();
   }
   catch (IOException e)
   {
       throw new RuntimeException(e);
   }
}

-1

재정의 된 메서드에서 try-catch 블록으로 예외를 포착 할 수 있습니다. 그러면 throws- 문을 선언 할 필요가 없습니다.


2
물론입니다.하지만 예외를 삼킬 것입니다. 이것은 제가 달성하려는 것과 정확히 반대입니다.)
Jürgen Steinblock 2010

-1

RuntimeException 또는 RuntimeException 자체에서 파생 된 모든 예외를 사용할 수 있습니다.

또는

예외 발생 코드에 대해 try-block을 사용하고 거기에서 처리하십시오.

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