발생 될 수없는 확인 된 예외를 처리하는 방법


35

예:

foobar = new InputStreamReader(p.getInputStream(), "ISO-8859-1");

인코딩이 하드 코딩되고 정확하기 때문에 생성자는 사양에 선언 된 UnsupportedEncodingException을 throw하지 않습니다 (Java 구현이 중단되지 않으면 어쨌든 손실됩니다). 어쨌든 Java는 어쨌든 그 예외를 처리하도록 강요합니다.

현재는

try {
    foobar = new InputStreamReader(p.getInputStream(), "ISO-8859-1");
}
catch(UnsupportedEncodingException e) { /* won't ever happen */ }

어떤 아이디어가 더 나아질 수 있습니까?


4
실제 문제를 해결하려면이 테스트가 실제로 작동하는지 확인하기 위해 단위 테스트를 작성하십시오.
Jay Elston

1
`새로운 ImpossibleException을 던지십시오 ( "우주를 재부팅하십시오. 일이 엉망이되었습니다", e);
Chris Cudmore

1
"일어나지 않을"것입니다

Thorbjørn Ravn Andersen : 프로그램을 변경 한 후 최소한 현재 상태에서는 입력 데이터 세트가 예외를 트리거 할 수 없습니다.
user281377

위의 특정 예에서 메소드는 지원되는 인코딩으로 호출되는지 여부를 인식하지 못하기 때문에 예외가 발생합니다. 표준 문자셋이 있다고 가정 한 다른 생성자가 있다면 예외를 던질 것이라고 선언 할 필요가 없습니다.
Jordan

답변:


27

저의 습관은 단지 안전한쪽에 assert있어야 캐치 블록 에 넣는 것 입니다. 누군가 try나중에 블록 의 내용을 변경할 수 있으며 코드가 실패하는지 알고 싶습니까?


좋은 생각; 간단한 assert false;것은 너무 많은 혼란을 유발하지 않으며 catch 블록이 절대 입력되지 않을 것이라고 가정합니다.
user281377

5
@ammoQ 또는 메시지를 추가하여 의도를 명확하게 할 수도 있습니다 assert false : "should never happen".
Péter Török

13
더 좋은 점은 "자바 문자 ISO-8859-1을 지원해야하기 때문에 발생하지 않을 것"이라고 덧붙였다.
dan04

3
assert어설 션이 활성화되었음을 나타냅니다. 나는 UnexpectedException(또한 스택 추적을 할 수 있다는 이점이 있습니다 ...)를 던졌습니다 .
Chop

35

만약 내가 이런 일이 일어나지 않아야한다는 로그 / 오류를 볼 때마다 센트를 받았다면, 나는 2 센트가되었을 것이다. 하지만 여전히 ...

캐치 블록이 비어 있으면 거미가 따끔 거리고 가장 좋은 코드 분석기 도구가 불평합니다. 나는 그것들을 비워 두는 것을 피할 것입니다. 물론, 이제는 오류가 발생할 수 없다는 것을 알고 있지만 1 년 후 누군가 "ISO-8859-1"의 전체 검색을 수행하고 갑자기 버그를 찾기가 매우 어려울 수 있습니다.

assert false제안은 훌륭하지만 주장이 때문에 비활성화 할 수 있습니다 런타임에, 그들은 보장되지 않습니다. RuntimeException대신에 사용하겠습니다 . 클래스를 호출하여 잡을 필요는 없으며 클래스가 발생하면 전체 정보를 제공하는 스택 추적이 생깁니다.


28

나는 항상 다음과 같이했다 :

try {
    foobar = new InputStreamReader(p.getInputStream(), "ISO-8859-1");
} catch(UnsupportedEncodingException e) {
    throw new AssertionError(e);
}

조금 장황 할 수도 있지만 (Java는 ...) 적어도 불가능한 경우 어설 션 오류가 발생합니다.

Java 구현이 중단 된 경우 불가능을 무시하는 대신 가능한 빨리 오류 메시지를 최대한 빨리 받고 싶을 것입니다. 자바 구현이 파손되지 않은 경우에도 그리고, 누군가가 변경되었을 수 있습니다 귀하의 코드를 "UTF8"(- 그것은 있었어야 죄송합니다 "UTF-8"?).

이것은 해야 처음부터 런타임 예외왔다. JDK는 이런 종류의 잘못된 선택으로 가득 차 있습니다.


4
실제 나쁜 결정 (또는 원하는 경우 생략)은 Java에 필요한 6 개의 문자 세트에 대해 사전 정의 된 문자 세트 인스턴스가 없다는 것입니다. foobar = new InputStreamReader(p.getInputStream(), Charset.ISO_8859_1);-지금은 더 나쁘지 않고 실수를 한 번도 피하지 않겠습니까?
user281377

3
구아바 도서관에는 수많은 것들이 있습니다. 인생을 더 쉽게 만듭니다.

3
Java 1.7 이상에는 문자 세트 상수가 정의되어 있습니다 ( docs.oracle.com/javase/7/docs/api/java/nio/charset/…) . 다음과 같이 사용하십시오 : StandardCharsets.UTF_8.displayName ()
Michael

4

이 코드를 볼 수있는 유일한 개발자라면 괜찮다고 말 하겠지만, 그렇지 않다면 실제 가능성으로 취급하거나 최소한 "일어나지 않는"주석을 더 유용한 것.


4

나를 가장 귀찮게하는 이러한 예외 중 일부는 내 코드 적용 범위가 손상된다는 것입니다.

적용 범위에 대해 강박 적 시도를 할 때 "발생할 수 없음"(또는 "US-ASCII"포함을 잊어 버린 돌연변이 JVM을 사용하는 경우) 시도 / 캐치를 롤업합니다. 시도 / catch를 캡슐화하고 여기에 언급 된 방법 중 하나를 사용하여 확인 된 예외를 대체하는 클래스 및 메소드 (일반적으로 확인되지 않은 예외를 snide 메시지로 던짐).

그런 다음 코드 범위는 유틸리티 클래스에서 적중하지만 코드 주위에 흩어져있는 해당 작업에 대한 모든 참조는 아닙니다.

때로는 실제로 코 히어 런트 의미가있는 클래스에서 작업처럼 롤업하는 데 시간이 걸릴 것입니다. 그러나 팀 동료들에게는 현재 상황이 매우 분명하기 때문에 가능한 한 최고의 디자인에 대해 걱정할 필요없이 최대한 단순하게 유지합니다.

그러나 언급 한 바와 같이 구아바 및 기타 라이브러리는이 고통을 완화시킬 수있는 방법이 있지만 기본적으로 동일한 전략입니다. 메인 코드가 적용 범위를 벗어나지 않도록 성가심을 무대 밖으로 옮기십시오.

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