Java 8의 예외 유형 추론의 독특한 기능
이 사이트에서 다른 답변에 대한 코드를 작성하는 동안 다음과 같은 특징을 발견했습니다.
static void testSneaky() {
final Exception e = new Exception();
sneakyThrow(e); //no problems here
nonSneakyThrow(e); //ERRROR: Unhandled exception: java.lang.Exception
}
@SuppressWarnings("unchecked")
static <T extends Throwable> void sneakyThrow(Throwable t) throws T {
throw (T) t;
}
static <T extends Throwable> void nonSneakyThrow(T t) throws T {
throw t;
}
첫째, 왜 sneakyThrow
호출이 컴파일러에 대해 괜찮은지 혼란 스럽습니다 . T
확인되지 않은 예외 유형에 대한 언급이 없는 경우 가능한 유형은 무엇입니까?
둘째, 작동한다는 것을 이것이 받아들이-plane 왜 컴파일러가 nonSneakyThrow
호출 에 대해 불평 합니까? 그들은 매우 존경합니다.
의 T는 sneakyThrow
로 추론 RuntimeException
됩니다. 유형 추론에 대한 언어 사양 ( http://docs.oracle.com/javase/specs/jls/se8/html/jls-18.html ) 에서 따를 수 있습니다.
첫째, 섹션 18.1.3에 메모가 있습니다.
양식의 경계
throws α
는 순전히 정보 제공 용입니다. 가능한 경우 확인 된 예외 유형이 아니도록 α의 인스턴스화를 최적화하도록 해결을 지시합니다.
이것은 아무 영향도 없지만 특별한 경우에 유추 된 예외 유형에 대한 자세한 정보를 제공하는 해상도 섹션 (18.4)을 알려줍니다.
... 그렇지 않으면 결합 세트가 포함되어있는 경우
throws αi
, 및 αi 적절한 상한은 기껏해야하고,Exception
,Throwable
, 및Object
, 그때의 티 =RuntimeException
.
이 경우에 적용됩니다 sneakyThrow
- 상한은 유일한 Throwable
이므로 사양에 따라 T
추정 RuntimeException
되므로 컴파일됩니다. 방법의 본문은 중요하지 않습니다. 확인되지 않았으므로 실행에 성공하여 타임 체크 예외 시스템을 무효화합니다.
nonSneakyThrow
방법 의이 같은 그 컴파일되지 않습니다 T
낮은의 하한 가지고있다 Exception
(즉 T
의 슈퍼해야 우리한다 Exception
, 또는 Exception
그이, 그래서 그것 때문에이 호출되고있는 유형으로, 체크 예외 인 자체) T
로 추정됩니다 Exception
.
유형 추론이 유형 변수에 대해 단일 상한을 생성하는 경우 일반적으로 상한이 솔루션으로 선택됩니다. 예를 들어이면 T<<Number
해는 T=Number
입니다. Integer
, Float
등도 제약보기 조건을 충족 할 수 있지만 대신 선택할 이유가 없습니다 Number
.
즉, 위해도의 경우와 throws T
자바 5-7 : T<<Throwable => T=Throwable
. (Sneaky throw 솔루션은 모두 명시 적 <RuntimeException>
유형 인수가 해당, 즉 이름 추론 <Throwable>
됩니다.)
java8에서는 람다가 도입되는 문제가 있습니다. 이 경우를 고려하십시오
interface Action<T extends Throwable>
{
void doIt() throws T;
}
<T extends Throwable> void invoke(Action<T> action) throws T
{
action.doIt(); // throws T
}
빈 람다로 호출하면 T
무엇으로 추론을 호출합니까?
invoke( ()->{} );
에 대한 유일한 제약 T
은 상한 Throwable
입니다. java8의 초기 단계에서는 T=Throwable
추론됩니다. 제출 내가 한이 보고서를 참조하십시오 .
그러나 이것은 Throwable
빈 블록에서 확인 된 예외 를 추론하기에는 꽤 어리석은 일 입니다. 보고서에서 제안이 제안되었습니다 (JLS에서 제안한 제안)-
If E has not been inferred from previous steps, and E is in the throw clause,
and E has an upper constraint E<<X,
if X:>RuntimeException, infer E=RuntimeException
otherwise, infer E=X. (X is an Error or a checked exception)
즉, 상한이 Exception
또는 Throwable
인 경우 RuntimeException
솔루션으로 선택 합니다. 경우가이 있다 상한의 특정 하위 유형을 선택하는 좋은 이유.
사용를 sneakyThrow
하면 유형 T
이 특정 유형이 없는 제한된 제네릭 유형 변수입니다 (유형의 출처가 없기 때문에).
사용을 nonSneakyThrow
하면 유형 T
이 인수와 동일한 유형이므로 예제에서 T
의 nonSneakyThrow(e);
는 Exception
입니다. 으로는 testSneaky()
던져 선언하지가 않는 Exception
오류가-display됩니다.
이것은 확인 된 예외가있는 Generics의 알려진 간섭입니다.
'IT' 카테고리의 다른 글
Google App Engine Java의 RESTful 애플리케이션? (0) | 2020.09.25 |
---|---|
헤더 내부 앵커 또는 그 반대 -SEO와 관련하여 다른 점이? (0) | 2020.09.25 |
std :: stack이 기본적으로 std :: deque를 사용하는 이유는 무엇입니까? (0) | 2020.09.25 |
에 JavaScript 코드를 넣는 다른 방법의 차이점은 (0) | 2020.09.25 |
XIB 파일을 연 후 Xcode 6.3이 멈추거나 중단됨 (0) | 2020.09.25 |