코드에서 런타임 예외를 처리하는 것이 좋지 않습니까?


11

Java 응용 프로그램에서 작업 중이며 런타임 예외가 여러 곳에서 처리되는 것을 볼 수 있습니다. 예를 들어

try {
    // do something
} catch(NullPointerException e) {
    return null;
}

내 질문은 언제 런타임 예외를 처리하는 것이 좋은 습관입니까? 예외는 언제 처리해야합니까?


7
-1 :이 광범위하고 모호한 질문에 대한 단일 답변은 없습니다. 초점이 맞지 않은 질문에 단일 답변을 제공하는 것은 불가능합니다. 이 질문은 끔찍합니다. 의심스러운 부분의 구체적인 예를 제공해주십시오 .
S.Lott

@ S.Lott이 경우에는 "좋은"합리성이없는 경우라고 생각하는 프로그래머의 하위 집합이있는 것처럼 보이므로이 점에 동의하지 않습니다.
SoylentGray

2
@Chad : "이것은"좋은 "합리성이없는 경우입니다. 사실 일 수도 있습니다. 그러나 가능한 대답은 "그것은 달려있다"는 것입니다. 따라서 질문은 잘못된 것 같습니다.
S.Lott

답변:


18

때에 따라 다르지.

예를 들어, 제공된 문자열을 구문 분석 할 수없는 경우 (RTE 인) Integer#parseInt던집니다 NumberFormatException. 그러나 사용자가 정수 텍스트 필드에 "x"를 썼기 때문에 앱이 중단되는 것을 원하지 않습니까? 문자열을 먼저 구문 분석하지 않으면 문자열을 구문 분석 할 수 있는지 여부를 어떻게 알 수 있습니까? 따라서이 경우 RTE는 일종의 오류 메시지를 발생시키는 오류 신호일뿐입니다. 체크 된 예외 여야 한다고 주장 할 수 있지만 할 수있는 일은 아닙니다.


2
나는 "그것은 달려있다"에 동의하지만, 당신의 파싱 예제는 오히려 API 디자인이 나쁜 것 같습니다. Integer#parseInt실제로 Maybe<Integer>대신 대신 반환하고 예외를 발생시키지 않아야합니다.
Jörg W Mittag

3
@ Jörg W Mittag : API 디자인이 좋지 않다는 데 동의하지만 우리가 다루어야 할 실제 세계입니다. 제대로 throw 가능 객체를 처리하는 방법 / 반환 값은 세상이 방법에 따라 달라 실제로 는 최적의 방법에하지, 작동 한다 :-) 일
투입 Joonas Pulakka

여기서 요점은 예상 조건 (정수가 아닌 사용자 입력)에 의미있는 것을 할 수 있다는 것입니다. NPE를 삼키는 것은 나쁜 스타일이며 기존 프로그래밍 오류를 막을 것입니다.
Jürgen Strobel

7

NullPointerExceptions는 일반적으로 null 검사가 누락되었음을 나타냅니다. 따라서 이와 같이 잡는 대신 예외를 발생시키지 않도록 적절한 null 검사를 추가해야합니다.

그러나 때로는 RunTimeExceptions를 처리하는 것이 좋습니다. 예를 들어, 적절한 위치에 널 검사를 추가하기 위해 코드를 수정할 수 없거나 예외가 NullPointerException 이외의 다른 경우입니다.

예외 처리의 예는 끔찍합니다. 그렇게하면 스택 추적과 문제에 대한 정확한 정보가 손실됩니다. 그리고 아마도 다른 장소에서 다른 NullPointerException을 발생시키고 발생한 문제와 해결 방법에 대한 잘못된 정보를 얻을 수 있으므로 실제로 해결하지 못합니다.


1
null 확인이 성능 측면에서 더 나은 결정이라고 덧붙이고 싶습니다.
Mahmoud Hossam

... 여전히 한 곳에서 "실패해서는 안되는"수십 개의 할당을 수행하는 경우 각각에 대해 null 검사를 추가하면 코드가 어리석게 혼란 될 수 있습니다. 모든 예외를 처리 return null;하는 것이 더 나은 해결책이 될 것입니다.
SF.

아마도 java와 다른 것을 혼동하고있을 것입니다 (예 : C ++). 할당이 실패하면 OutOfMemoryError 또는 이와 유사한 것을 얻지 만 결코 null 포인터가 아닙니다. 예외 대신 null 반환을 숨기는 것은 코드가 다른 곳에서 폭발하기를 기다리는 오류를 숨기는 것입니다.
deadalnix

new슬로우 std::bad_allocC ++에서.
R. Martinho Fernandes

새 연산자가 오버로드되지 않았다고 가정하는 것이 일반적입니다. C ++에서는 모든 일이 일어날 수 있습니다.) 그러나 C의 malloc을 말합시다. 중요한 점은 당신이 자바에서 그것을 얻지 못했다는 것입니다.
deadalnix

4

예상 예외를 처리합니다. (DB 읽기 / 쓰기 오류처럼). 예기치 않은 예외가 발생합니다. 다른 곳에서 예외를 기대하고 논리를 가질 수 있습니다.


2

예외는 그저 .. 예외입니다. 예외를 사용할 때 모범 사례는 예외를 사용하여 예상되는 것과 상반되는 상황을 처리하는 것입니다. 고전적인 예는 FileNotFoundException이며 파일이 단순히 없을 때 발생합니다. 파일의 존재를 테스트하는 경우 File.exists ()를 사용하면 단순히 10 피트 스틱으로 proding하기 때문에 무언가를 쳤는지 확인할 수 있습니다.

시도 캐치에서 파일을 둘러싸고 존재하는 것처럼 파일을 사용하여 기술적으로 동일한 결과를 얻을 수 있지만 A) 예외는 일반적으로 리소스 비용이 많이 들며 B) 프로그래머는 파일이 존재하는 경우 파일이 존재한다고 가정합니다. 시도 캐치에서 프로그램의 전반적인 혼란을 더합니다.

데이터베이스에서 일부 값을 가져 오는 메소드를 작성하는 상황이 많이 있습니다. 수천 가지 문제가 발생할 수 있으며 작은 정보가 하나만 필요한 경우 5 가지 예외가 포함 된 try catch 목록으로 호출을 둘러싸는 것이 불편합니다. 그래서 fetch 메소드에서 예외를 잡을 것입니다. 문제가 발생하면 데이터베이스 연결을 닫거나 finally 절의 내용을 닫기 위해 적절한 조치를 취하고 null을 반환합니다. 이것은 코드를 단순화 할뿐만 아니라 "null"이 예외에서 얻을 수있는 것과 동일한 메시지를 전송하기 때문에 좋은 방법입니다. 페치 메소드에서 예외 세부 사항을 관리하지만 상황이 발생할 때 수행 할 작업을 관리하십시오.

예를 들면 다음과 같습니다.

Integer getUserCount() {
   Integer result = null;
   try {
      // Attempt to open database and retrieve data
   } catch (TimeoutException e) {
      logger.error("Got a watch?");
   } catch (MissingDatabaseException e) {
      logger.error("What are you smoking?");
   } catch (PermissionsToReadException e) {
      logger.error("Did you *really* think you were getting away with that?");
   } catch (PressedSendButtonToHardException e) {
      logger.error("Seriously.. just back away from the computer... slowly..");
   } catch (WTFException e) {
      logger.error("You're on your own with this one.. I don't even know what happened..");
   } finally {
      // Close connections and whatnot
   }
   return result;
}

void doStuff() {
   Integer result = getUserCount();
   if(result != null) {
       // Went as planned..
   }
}

6
File.exists ()를 사용하고 결과에 의존하는 경우 File.exists ()와 File.open () 사이에서 파일을 바로 삭제하면 경쟁 조건이 발생할 수 있습니다. 이로 인해 보안에 중요한 버그가 발생하면 공격자는 의도적으로이 조건을 유발할 수 있습니다. 이 때문에 때로는 작업을 원 자성으로 유지하는 것이 좋습니다. 즉, 시도하고 예외를 잡는 것이 좋습니다.
user281377

1
또한 응용 프로그램을 실행하기 위해 존재해야하는 파일이 있습니다. 이는 예외적 인 조건입니다. 응용 프로그램이 작동하기 위해 있어야하는 파일이 있으면 파일을 읽지 말고 예외적 인 경우에 대한 예외를 처리 할 이유가 없습니다. 나는 그것이 의도를 더 명확하게 만든다고 믿는다.
토마스 오웬스

이것은 null을 반환하는 잘못된 결정입니다. 어느 시점에서 NullPointerException이 발생하고 실제로 무엇이 잘못되었는지 디버깅하기가 어렵습니다. 누군가 언젠가 널 점검을 잊어 버리기 때문입니다.
deadalnix

@ deadalnix : 다른 방법으로 시도 캐치로 둘러싸는 것을 쉽게 잊을 수 있다고 주장 할 수 있습니다. 차이점은 기능의 문제가 아니라 스타일의 문제입니다.
Neil

@ ammoQ : 동의하지 않습니다. File.exists ()를 사용해야한다고 생각하고 사용하기 전에 삭제되는 드문 상황에서는 예외가 적절합니다. 차이점은 당신이 캐치를 유지하는 곳입니다. 예상치 못한 오류에 대해 담요 예외 캐처를 작성하여 기록하고보고하십시오.
Neil

-5

예, 올바른 처리 런타임 예외는 좋은 방법이 아닙니다. 비용이 많이 들고 / 메모리를 많이 사용하는 것으로 간주되기 때문입니다.


5
안녕하세요 prassee, 당신은 당신의 답변을 자세히 설명 할 수 있습니까? 사실, 참조 또는 경험으로 백업되지 않은 원 라이너는별로 도움이되지 않습니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.