Java에서 확인 된 예외와 확인되지 않은 예외 이해


703

" 유효한 자바 "에 있는 조슈아 블로흐는

복구 가능한 조건에 대해 확인 된 예외를 사용하고 프로그래밍 오류에 대해 런타임 예외를 사용하십시오 (제 2 판의 항목 58).

내가 이것을 올바르게 이해하는지 봅시다.

다음은 확인 된 예외에 대한 이해입니다.

try{
    String userInput = //read in user input
    Long id = Long.parseLong(userInput);
}catch(NumberFormatException e){
    id = 0; //recover the situation by setting the id to 0
}

1. 위의 사항은 확인 된 예외로 간주됩니까?

2. RuntimeException이 검사되지 않은 예외입니까?

확인되지 않은 예외에 대한 이해는 다음과 같습니다.

try{
    File file = new File("my/file/path");
    FileInputStream fis = new FileInputStream(file);   
}catch(FileNotFoundException e){

//3. What should I do here?
    //Should I "throw new FileNotFoundException("File not found");"?
    //Should I log?
    //Or should I System.exit(0);?
}

4. 이제 위의 코드도 확인 된 예외가 될 수 없습니까? 이런 상황을 복구하려고 할 수 있습니까? 할 수 있습니까? (참고 : 내 세 번째 질문은 catch위 의 내용입니다)

try{
    String filePath = //read in from user input file path
    File file = new File(filePath);
    FileInputStream fis = new FileInputStream(file);   
}catch(FileNotFoundException e){
    //Kindly prompt the user an error message
    //Somehow ask the user to re-enter the file path.
}

5. 사람들은 왜 이것을 하는가?

public void someMethod throws Exception{

}

왜 예외가 발생하게합니까? 오류를 더 빨리 처리하지 않습니까? 왜 거품이 일어 납니까?

6. 정확한 예외를 버블 링하거나 예외를 사용하여 마스킹해야합니까?

아래는 내 독서입니다

Java에서 언제 점검 된 예외를 작성해야하며 언제 런타임 예외 여야합니까?

확인 및 확인되지 않은 예외를 선택하는시기


6
확인되지 않은 예외의 좋은 예가 있습니다. DataSeries항상 시간 기반 순서로 유지 해야하는 데이터를 보유 하는 클래스가 있습니다. DataPoint끝에 새 항목 을 추가하는 방법이 있습니다 DataSeries. 내 코드가 모두 프로젝트 전체에서 올바르게 작동 DataPoint하는 경우 끝에 이미 날짜가있는 끝에 추가해서는 안됩니다. 전체 프로젝트의 모든 모듈은이 트루 즘으로 구축됩니다. 그러나이 조건을 확인하고 확인되지 않은 예외가 발생하면 throw합니다. 왜? 이런 일이 발생하면 누가이 작업을 수행하고 있는지 알고 싶습니다.
Erick Robertson

3
더 혼란을 더합니다. 많은 사람들이 ~ 10 년 전에 확인 된 예외를 옹호하고 있었지만, 요즘에는 "확인 된 예외가 나쁘다"라는 관점이 점점 더 이동하고 있습니다. (그러나 나는 그것에 동의하지 않습니다)
Kaj

10
그것과 관련이있는 무언가가있을 때 예외를 처리하는 것이 유용합니다. 그렇지 않으면 호출자가 처리하도록하십시오. 로깅 및 발생하지 않은 척은 일반적으로 유용하지 않습니다. 다시 던지는 것은 무의미합니다. RuntimeException에 래핑하는 것은 일부 사람들이 생각하는 것만 큼 유용하지 않으며 컴파일러가 당신을 돕는 것을 멈추게합니다. (IMHO)
Peter Lawrey

40
검사 / 검사되지 않은 예외에 대한 포괄적 인 오해의 여지가있는 용어 사용을 중단해야합니다 . 그것들은 체크 명령체크되지 않은 예외라고합니다.
축복받은

3
또한 5 포인트 public void method_name이 예외를 throw한다고 생각했습니다. 일부 사람들은 왜 그렇게합니까?
Maveň ツ

답변:


474

많은 사람들은 확인 된 예외 (즉, 명시 적으로 잡거나 다시 던져야하는 예외)를 전혀 사용해서는 안된다고 말합니다. 예를 들어 C #에서 제거되었으며 대부분의 언어에는 없습니다. 따라서 RuntimeException(확인되지 ​​않은 예외) 의 하위 클래스를 항상 던질 수 있습니다

그러나 확인 된 예외는 유용하다고 생각합니다.이 예외는 API 사용자에게 예외 상황 (복구 가능한 경우)을 처리하는 방법을 생각하도록 강요 할 때 사용됩니다. 확인 된 예외가 Java 플랫폼에서 과도하게 사용되어 사람들이 예외를 미워하게 만드는 것입니다.

여기 주제에 대한 확장 된 견해가 있습니다 .

특정 질문에 관해서는 :

  1. NumberFormatException체크 예외를 고려?
    번호 NumberFormatException가 선택되어 있지 않습니다 (=는의 하위 클래스입니다 RuntimeException). 왜? 모르겠어요 (그러나 방법이 있어야했습니다 isValidInteger(..))

  2. RuntimeException체크되지 않은 예외?
    그렇습니다.

  3. 여기서 무엇을해야합니까?
    이 코드의 위치와 수행하려는 작업에 따라 다릅니다. UI 계층에있는 경우이를 포착하고 경고를 표시하십시오. 그것이 서비스 계층에 있다면-전혀 잡지 마십시오-거품을 내십시오. 예외를 삼키지 마십시오. 대부분의 경우에 예외가 발생하면 다음 중 하나를 선택해야합니다.

    • 그것을 기록하고 반환
    • 다시 던지십시오 (메서드에 의해 던져 질 것이라고 선언하십시오)
    • 생성자에서 현재 예외를 전달하여 새 예외를 구성
  4. 이제 위의 코드도 검사 예외가 될 수 없습니까? 이런 상황을 복구하려고 할 수 있습니까? 할 수 있습니까?
    그랬을 수도 있습니다. 그러나 확인되지 않은 예외를 잡는 데 방해가되는 것은 없습니다.

  5. 사람들 Exception이 throws 절에 클래스 를 추가하는 이유는 무엇 입니까?
    사람들이 무엇을 잡아서 다시 던질지를 고려하기가 게으 르기 때문에 대부분의 경우 던지는 Exception것은 나쁜 습관이므로 피해야합니다.

아아, 잡을 때, 다시 던질 때, 사용할 때 및 확인되지 않은 예외를 사용할 때를 결정할 수있는 단일 규칙은 없습니다. 나는 이것이 많은 혼란과 나쁜 코드를 유발한다는 데 동의합니다. 일반적인 원칙은 Bloch가 명시합니다 (일부 인용). 그리고 일반적인 원칙은 처리 할 수있는 레이어에 예외를 다시 던지는 것입니다.


36
예외 던지기와 관련하여 사람들이 게으 르기 때문에 항상 그런 것은 아닙니다. 프레임 워크를 구현할 때 프레임 워크 사용자가 예외를 throw 할 수있게하는 것이 일반적입니다. 예를 들어 JSE
Kaj

10
@Kaj-네, Callable, interceptors 등과 같은 일반적인 것들이 특별한 경우입니다. 그러나 대부분의 경우 사람들이 게으
르기

7
re : 3.1 "로그인 및 반환"신중하게 그렇게하십시오. 이것은 먹거나 숨기고 예외와 매우 가깝습니다. 나는 문제를 나타내지 않는 무언가를 위해 이것을 할 것입니다. 로그가 넘쳐 너무 쉽게 무시됩니다.
Chris

4
"API 사용자에게 예외적 인 상황을 처리하는 방법을 강요하도록 강요하려는 경우"-원하지 않는 사람은 누구도 강요 할 수 없습니다. 만약 그들이 생각하고 싶지 않다면, 그들은 아무 것도하지 않거나 나쁜 에러 정보를 삭제하거나 방해하는 나쁜 예외 블록을 쓸 것입니다. 이것이 확인 된 예외가 실패한 이유입니다.
adrianos

3
@adrianos "... 당신이 원치 않으면 누군가가 생각하도록 강요 할 수 없다 ...."이 생각의 선으로 우리는 또한 컴파일 오류를 제거 할 수있다. 인수를 계속해서 반복해서 확인 된 예외에 실패로 레이블링하는 데있어 가장 나쁜 설명이라고 생각합니다. 부수적으로, 필자는 컴파일 (및 실제로 런타임 오류)이 desing으로 효과적으로 불가능하게되는 언어 이전에 보았습니다. 그 길은 매우 어두운 곳으로 이어졌습니다.
Newtopian

233

무언가가 "체크 된 예외"인지 여부는 포착 여부 또는 catch 블록에서 수행하는 작업과 관련이 없습니다. 예외 클래스의 속성입니다. 의 서브 클래스를 아무거나 Exception 제외RuntimeException와 그 서브 클래스는 체크 예외입니다.

Java 컴파일러는 확인 된 예외를 포착하거나 메소드 서명에서이를 선언하도록합니다. 프로그램 안전성을 향상시켜야했지만 대다수의 의견은 그것이 생성하는 디자인 문제의 가치가 없다고 생각합니다.

왜 예외가 발생하게합니까? 핸들 오류가 빠를수록 좋습니다. 왜 거품이 일어 납니까?

즉, 전체이기 때문에 예외는. 이 가능성이 없으면 예외가 필요하지 않습니다. 이를 통해 원래 발생한 저수준 방법으로 오류를 처리하지 않고 선택한 수준에서 오류를 처리 할 수 ​​있습니다.


3
감사합니다! 나는 때때로 쇠약해진 원칙 때문에 쓰레기를 내 법에서 제외시킨다. 팀의 개발자 중 한 명이 예외를 처리하기 위해 잘못된 xpath 식을 입력하려고합니다. 우연히도 예외를 포착하고 코드 검토에서 예외를 듣지 않습니다.
jeremyjjbrown

12
"RuntimeException 및 해당 서브 클래스를 제외하고 Throwable의 서브 클래스 인 것은 점검 된 예외입니다." -당신의 진술이 잘못되었습니다. 오류는 Throwable을 상속받으며 확인되지 않습니다.
Bartzilla

8
@JonasEicher : 기본적으로 예외의 주요 장점은 호출 스택에서 오류를 처리 할 위치를 선택할 수 있다는 점입니다. 오류 처리 아티팩트가 전혀없는 계층을 유지하면서 종종 매우 높습니다. 확인 된 예외는 그 이점을 정확히 파괴합니다. 또 다른 문제는 확인 / 확인되지 않은 구별이 예외 클래스와 연결되어 예외 클래스의 개념 분류를 나타내며, 반드시 관련이없는 두 가지 측면을 혼합한다는 것입니다.
Michael Borgwardt

2
"하지만 대다수의 의견은 그것이 디자인 문제를 일으킬 가치가 없다고 생각합니다." -인용 부탁해?
kervin

3
@Bartzilla 예. 완전성을 위해 다음과 같이 javadoc이 Throwable말한 것처럼 : "Throwable 및 Throwable의 모든 서브 클래스가 RuntimeException 또는 Error의 서브 클래스가 아닌 경우에도 확인 된 예외로 간주됩니다."
Bart van Heukelom

74
  1. 위의 사항은 확인 된 예외로 간주됩니까? 아니 당신이 예외를 처리하는 사실은 그것은하지 않습니다 Checked Exception그것은 경우 RuntimeException.

  2. RuntimeExceptionunchecked exception? 예

Checked Exceptions이다 subclassesjava.lang.Exception Unchecked Exceptions이다 subclassesjava.lang.RuntimeException

확인 된 예외를 던지는 호출은 try {} 블록으로 묶거나 메소드의 호출자에서 위 레벨에서 처리되어야합니다. 이 경우 현재 메소드는 호출자가 예외를 처리하기 위해 적절한 조치를 취할 수 있도록 해당 예외를 처리한다고 선언해야합니다.

도움이 되었기를 바랍니다.

Q : 정확한 예외를 버블 링하거나 예외를 사용하여 마스킹해야합니까?

A : 그렇습니다. 이것은 매우 좋은 질문이며 중요한 디자인 고려 사항입니다. Exception 클래스는 매우 일반적인 예외 클래스이며 내부 하위 수준 예외를 래핑하는 데 사용할 수 있습니다. 사용자 정의 예외를 작성하고 그 안에 랩핑하는 것이 좋습니다. 그러나 큰 문제는 근본적인 근본 원인을 절대 모호하게하지 않습니다. 예를 들어 Don't ever다음을 수행하십시오.

try {
     attemptLogin(userCredentials);
} catch (SQLException sqle) {
     throw new LoginFailureException("Cannot login!!"); //<-- Eat away original root cause, thus obscuring underlying problem.
}

대신 다음을 수행하십시오.

try {
     attemptLogin(userCredentials);
} catch (SQLException sqle) {
     throw new LoginFailureException(sqle); //<-- Wrap original exception to pass on root cause upstairs!.
}

원래 근본 원인을 제거하면 복구를 넘어 실제 원인이 사라지는 것은 프로덕션 지원 팀에게 악의적입니다. 응용 프로그램 로그 및 오류 메시지 만 액세스 할 수 있습니다. 후자는 더 나은 디자인이지만 개발자가 기본 메시지를 발신자에게 전달하지 못하기 때문에 많은 사람들이 자주 사용하지 않습니다. 따라서 Always pass on the actual exception응용 프로그램 별 예외에 싸여 있는지 여부를 확인 하십시오 .

시선 잡기 RuntimeExceptions

RuntimeException일반적으로 s는 시도되지 않아야합니다. 그것들은 일반적으로 프로그래밍 오류를 알리기 때문에 혼자 두어야합니다. 대신 프로그래머는 오류가 발생할 수있는 일부 코드를 호출하기 전에 오류 조건을 확인해야합니다 RuntimeException. 예를 들어 :

try {
    setStatusMessage("Hello Mr. " + userObject.getName() + ", Welcome to my site!);
} catch (NullPointerException npe) {
   sendError("Sorry, your userObject was null. Please contact customer care.");
}

이것은 나쁜 프로그래밍 관행입니다. 대신 null 점검은 다음과 같이 수행되어야합니다.

if (userObject != null) {
    setStatusMessage("Hello Mr. " + userObject.getName() + ", Welome to my site!);
} else {
   sendError("Sorry, your userObject was null. Please contact customer care.");
}

그러나 숫자 형식과 같은 오류 검사가 비싼 경우가 있습니다.

try {
    String userAge = (String)request.getParameter("age");
    userObject.setAge(Integer.parseInt(strUserAge));
} catch (NumberFormatException npe) {
   sendError("Sorry, Age is supposed to be an Integer. Please try again.");
}

여기서 사전 호출 오류 검사는 parseInt () 메서드 내에서 모든 문자열-정수 변환 코드를 복제하는 것을 의미하기 때문에 노력할 가치가 없으며 개발자가 구현하면 오류가 발생하기 쉽습니다. 따라서 try-catch를 사용하지 않는 것이 좋습니다.

그래서 NullPointerException하고 NumberFormatException모두 RuntimeExceptions하는 잡는 것은 NullPointerException내가 잡기 권장하면서 우아한 널 (null) 검사로 대체해야 NumberFormatException오류가 발생하기 쉬운 코드의 도입 가능성을 방지하기 위해 명시 적으로.


감사합니다. 당신이 품어 질문 하나 더 exception정확한 예외 최대해야 I 거품 또는 사용하여 마스크 Exception. 레거시 코드 위에 코드를 작성 Exception하고 모든 곳에서 거품을 일으켰습니다. 이것이 올바른 행동인지 궁금합니다.
탕 팜

1
이것은 매우 좋고 중요한 질문이며 설명을 포함하도록 내 대답을 편집했습니다.
d-live

대단히 감사합니다. 내용을 보여줄 수 LoginFailureException(sqle)있습니까?
Thang Pham

1
나는 그 물건에 대한 코드를 가지고 있지 않다. 방금 이름 등을 요리했다. java.lang.Exception이 보이면 4 개의 생성자가 있는데 그중 2 개가 java.lang.Throwable을 받아 들인다. 조각에서 나는 위의 가정 LoginFailureException확장 Exception및 생성자 선언public LoginFailureException(Throwable cause) { super(cause) }
D-라이브

주제에 대한 최상의 답변. 프로그래밍 예외로 인해 예외가 발생하기 때문에 런타임 예외를 포착해서는 안됩니다. "원본 근본 원인 매장을 제거하면 복구 이외의 실제 원인은 프로덕션 지원 팀에게는 악몽입니다. ​​응용 프로그램 로그 및 오류 메시지 만 있으면됩니다."라는 부분에 동의합니다.
huseyin

19

1 . 예외가 확실하지 않은 경우 API를 확인하십시오.

 java.lang.Object
 extended by java.lang.Throwable
  extended by java.lang.Exception
   extended by java.lang.RuntimeException  //<-NumberFormatException is a RuntimeException  
    extended by java.lang.IllegalArgumentException
     extended by java.lang.NumberFormatException

2. 예, 그리고 그것을 확장하는 모든 예외.

삼 . 동일한 예외를 잡아서 던질 필요가 없습니다. 이 경우 새 파일 대화 상자를 표시 할 수 있습니다.

4. FileNotFoundException 이미 확인 된 예외입니다.

도 5. someMethod예외를 잡기 위해 호출하는 메소드가 예상 되면 후자를 던질 수 있습니다. 그냥 "공을 통과"합니다. 사용 방법의 예는 자신의 개인 메소드에서 처리하고 대신 공개 메소드에서 예외를 처리하려는 경우입니다.

Oracle Doc 자체를 잘 읽어보십시오. http://download.oracle.com/javase/tutorial/essential/exceptions/runtime.html

설계자가 범위 내에서 발생할 수있는 포착되지 않은 모든 예외를 지정하도록 메소드를 강제하기로 결정한 이유는 무엇입니까? 메소드에 의해 발생 될 수있는 예외는 메소드의 공용 프로그래밍 인터페이스의 일부입니다. 메소드를 호출하는 사람은 메소드에 대해 수행 할 조치를 결정할 수 있도록 메소드가 발생할 수있는 예외에 대해 알아야합니다. 이러한 예외는 해당 메소드의 프로그래밍 인터페이스에서 매개 변수 및 리턴 값만큼이나 중요합니다.

다음 질문은 다음과 같습니다. "던질 수있는 예외를 포함하여 메소드의 API를 문서화하는 것이 좋으면 런타임 예외도 지정하지 않는 이유는 무엇입니까?" 런타임 예외는 프로그래밍 문제의 결과로 발생하는 문제를 나타내므로 API 클라이언트 코드는 합리적으로 복구하거나 어떤 방식 으로든 처리 할 것으로 예상 할 수 없습니다. 이러한 문제에는 0으로 나누는 것과 같은 산술 예외; null 참조를 통해 객체에 액세스하는 등의 포인터 예외; 너무 크거나 작은 인덱스를 통해 배열 요소에 액세스하려는 것과 같은 인덱싱 예외.

Java 언어 사양 에는 중요한 정보가 있습니다 .

throws 절에 명명 된 확인 된 예외 클래스는 구현 자와 메소드 또는 생성자의 사용자 간의 계약의 일부입니다 .

결론 IMHO는 당신 any 잡을 있다는 것입니다 RuntimeException. 그러나 당신은 계약의 일부가 아닌 것과 같은 점검되지 않은 예외를 유지해야 할 필요는 없습니다.


감사합니다. 당신이 품어 질문 하나 더 exception정확한 예외 최대해야 I 거품 또는 사용하여 마스크 Exception. 레거시 코드 위에 코드를 작성 Exception하고 모든 곳에서 거품을 일으켰습니다. 이것이 올바른 행동인지 궁금합니다.
탕 팜

1
@Harry 나는 나보다 더 많은 지식을 가진 사람들이 대답 할 수 있도록 할 것이다 : stackoverflow.com/questions/409563/…
Aleadam

10

1) 아니요, NumberFormatException은 검사되지 않은 예외입니다. 체크하지 않았기 때문에 잡았더라도 (필요하지는 않습니다). 서브 클래스가의 서브 클래스이기 때문 IllegalArgumentException입니다 RuntimeException.

2) RuntimeException확인되지 않은 모든 예외의 근본입니다. 의 모든 서브 클래스 RuntimeException는 체크되지 않습니다. Throwable오류를 제외한 다른 모든 예외 는 확인됩니다 (아래에 있음 Throwable).

3/4) 존재하지 않는 파일을 선택했음을 사용자에게 알리고 새 파일을 요청할 수 있습니다. 또는 사용자에게 잘못된 것을 입력했다고 알리는 것을 종료하십시오.

5) 던지고 잡는 'Exception'것은 나쁜 습관입니다. 그러나 더 일반적으로는 호출자가 처리 방법을 결정할 수 있도록 다른 예외를 처리 할 수 ​​있습니다. 예를 들어, 일부 파일 입력 읽기를 처리하기 위해 라이브러리를 작성했고 메소드에 존재하지 않는 파일이 전달 된 경우이를 처리하는 방법을 모릅니다. 발신자가 다시 묻거나 종료 하시겠습니까? 따라서 예외를 호출자에게 다시 체인을 던집니다.

대부분의 경우 unchecked Exception프로그래머가 입력을 확인하지 않았기 때문에 발생합니다 ( NumberFormatException첫 번째 질문 의 경우 ). 그렇기 때문에 예외를 생성하지 않는 더 우아한 방법이 있기 때문에 선택 사항을 잡을 수 있습니다.


감사합니다. 당신이 품어 질문 하나 더 exception정확한 예외 최대해야 I 거품 또는 사용하여 마스크 Exception. 레거시 코드 위에 코드를 작성 Exception하고 모든 곳에서 거품을 일으켰습니다. 이것이 올바른 행동인지 궁금합니다.
탕 팜

메소드가 예외를 던지도록 할 수도 있습니다 (이상적이지 않음). 또는 예외를 잡아서 더 나은 예외 (IOException 등)를 던지십시오. 모든 예외는 생성자에서 '원인'으로 예외를 취할 수 있으므로 사용해야합니다.
dontocsata

8

확인 됨-발생하기 쉽습니다. 컴파일 시간에 체크인했습니다.

예 : 파일 작업

확인되지 않음-데이터가 잘못되었습니다. 런타임에 체크인했습니다.

예 :

String s = "abc";
Object o = s;
Integer i = (Integer) o;

Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
    at Sample.main(Sample.java:9)

여기서 예외는 잘못된 데이터로 인한 것이며 컴파일 시간 동안 확인할 수 없습니다.


6

확인 된 예외는 컴파일 타임에 JVM 및 리소스 (files / db / stream / socket 등)와 관련하여 확인됩니다. 확인 된 예외의 원인은 컴파일 타임에 리소스를 사용할 수없는 경우 응용 프로그램이 catch / finally 블록에서이를 처리하기위한 대체 동작을 정의해야한다는 것입니다.

검사되지 않은 예외는 순전히 프로그래밍 방식의 오류, 잘못된 계산, 널 데이터 또는 심지어 비즈니스 로직 장애로 인해 런타임 예외가 발생할 수 있습니다. 코드에서 검사되지 않은 예외를 처리 / 캐치하는 것이 좋습니다.

http://coder2design.com/java-interview-questions/ 에서 가져온 설명


5

확인되지 않은 예외와 확인 된 예외의 차이점에 대한 필자가 가장 좋아하는 설명은 Java Tutorial 트레일 기사 인 " 확인되지 않은 예외-논쟁 "(이 게시물의 모든 기초를 얻는 것이 유감이지만 기본은 때로는 최고 임)에 의해 제공됩니다.

결론은 다음과 같습니다. 클라이언트가 예외에서 복구 할 것으로 예상되는 경우이를 확인 된 예외로 만듭니다. 클라이언트가 예외에서 복구 할 작업을 수행 할 수 없으면 검사하지 않은 예외로 설정하십시오.

"어떤 유형의 예외를 던질 것인가"의 핵심은 의미 론적이며 (어느 정도까지) 위의 인용문이 제공하고 훌륭한 지침입니다. 그들의 유용성).

나머지는 논리적이됩니다. 컴파일러는 어떤 예외에 대해 명시 적으로 응답 할 것으로 기대합니까? 클라이언트가 복구 할 것으로 예상되는 것.


5

마지막 질문에 대답하기 위해 (다른 사람들은 위에서 철저히 대답 한 것처럼 보입니다) "정확한 예외를 버블 링하거나 예외를 사용하여 숨길 수 있습니까?"

나는 당신이 다음과 같은 것을 의미한다고 가정합니다 :

public void myMethod() throws Exception {
    // ... something that throws FileNotFoundException ...
}

아니요, 항상 가능한 가장 정확한 예외 또는 그러한 목록을 선언하십시오 . 메소드를 던질 수 있다고 선언 한 예외는 메소드와 호출자 간의 계약의 일부입니다. 던지기 "FileNotFoundException"는 파일 이름이 유효하지 않아 파일을 찾을 수 없다는 것을 의미합니다. 발신자는 지능적으로 처리해야합니다. 던지는 것은 Exception"이봐, 쉰다. 거래." 어느 것이 매우 가난 API합니다.

첫 번째 기사에 대한 의견에는 "throws Exception"가 유효하고 합리적인 선언 인 몇 가지 예가 있지만, 대부분의 " normal"코드 의 경우에는 그렇지 않습니다 .


정확하게, 검사 예외 선언을 코드 문서의 일부로 만들고 소프트웨어 사용을 도와주십시오.
살바도르 발렌시아

5

런타임 예외 : 런타임 예외는 확인되지 않은 예외라고합니다. 다른 모든 예외는 점검 된 예외이며 java.lang.RuntimeException에서 파생되지 않습니다.

확인 된 예외 : 확인 된 예외는 코드 어딘가에서 발견되어야합니다. 확인 된 예외를 발생시키는 메소드를 호출하지만 확인 된 예외를 어딘가에 포착하지 않으면 코드가 컴파일되지 않습니다. 이것이 예외 확인이라고 불리는 이유입니다. 컴파일러는 처리 또는 선언되었는지 확인합니다.

Java API의 많은 메소드가 확인 된 예외를 처리하므로 작성하지 않은 메소드에서 생성 된 예외에 대처하기 위해 예외 핸들러를 작성하는 경우가 많습니다.


3

왜 예외가 발생하게합니까? 오류를 더 빨리 처리하지 않습니까? 왜 거품이 일어 납니까?

예를 들어, 클라이언트-서버 응용 프로그램이 있고 클라이언트가 찾을 수없는 일부 리소스를 요청했거나 사용자 요청을 처리하는 동안 서버 측에서 일부 오류가 발생했을 수 있습니다. 서버가 요청한 것을 얻지 못한 이유를 클라이언트에게 알려주기 위해 서버 측에서 throw 키워드를 사용하여 예외를 삼키거나 처리하는 대신 예외를 throw 하도록 코드가 작성됩니다. 그러면 클라이언트에게 어떤 오류가 발생했는지 암시 할 가능성이 없습니다.

참고 : 오류 유형에 대한 명확한 설명을 제공하기 위해 자체 예외 개체를 만들어 클라이언트에 던질 수 있습니다.


좋은 지적. 의미하는 것은 논리 흐름을 제어하고 응용 프로그램의 비즈니스 논리를 감독하는 가장 책임있는 최상위 계층으로 버블 링하는 것입니다. 예를 들어, 데이터베이스 계층이 중요한 정보가 누락되었거나 응답하지 않음을 클라이언트와 통신하는 것은 불가능합니다. 최상위 서버 계층으로 올라가면 중요한 오류 메시지로 클라이언트의보기를 새로 고치는 것이 간단합니다.
살바도르 발렌시아


3

확인 된 예외를 전혀 사용하지 않는 이유를 추가하고 싶습니다. 이것은 완전한 답변은 아니지만 귀하의 질문의 일부에 답변하고 다른 많은 답변을 보완한다고 생각합니다.

확인 된 예외가 관련 될 때마다 throws CheckedException메소드 서명에 어딘가 CheckedException가 있습니다 ( 확인 된 예외가 될 수 있음). 서명은 예외를 발생시키지 않으며 예외를 던지는 것은 구현의 한 측면입니다. 인터페이스, 메소드 시그니처, 부모 클래스,이 모든 것들은 구현에 의존해서는 안됩니다. 여기에서 확인 된 예외 사용 (실제로 throws메소드 서명 에 선언해야한다는 사실 )은 상위 인터페이스를 이러한 인터페이스 구현과 바인딩합니다.

예를 보여 드리겠습니다.

이처럼 멋지고 깔끔한 인터페이스를 보자

public interface IFoo {
    public void foo();
}

이제 우리는 foo()이와 같은 많은 메소드 구현을 작성할 수 있습니다.

public class Foo implements IFoo {
    @Override
    public void foo() {
        System.out.println("I don't throw and exception");
    }
}

Foo 클래스는 완벽합니다. 이제 클래스 바에서 첫 번째 시도를 해봅시다

public class Bar implements IFoo {
    @Override
    public void foo() {
        //I'm using InterruptedExcepton because you probably heard about it somewhere. It's a checked exception. Any checked exception will work the same.
        throw new InterruptedException();
    }
}

이 클래스 바는 컴파일되지 않습니다. InterruptedException은 검사 된 예외이므로, foo () 메소드 내에 try-catch를 사용하여 캡처하거나 예외를 던지고 있음을 선언해야합니다 ( throws InterruptedException메소드 서명에 추가 ). 여기 에서이 예외를 포착하고 싶지 않기 때문에 (위로 전파하여 다른 곳에서 올바르게 처리 할 수 ​​있기를 원합니다) 서명을 변경합시다.

public class Bar implements IFoo {
    @Override
    public void foo() throws InterruptedException {
        throw new InterruptedException();
    }
}

이 클래스 바는 컴파일되지 않습니다! Bar의 메소드 foo ()는 서명이 다르기 때문에 IFoo의 메소드 foo ()를 대체하지 않습니다. @Override 주석을 제거 할 수는 있지만 IFoo와 비슷한 인터페이스에 대해 프로그래밍 IFoo foo;하고 나중에 사용할 구현을 결정하려고합니다 foo = new Bar();. Bar의 메소드 foo ()가 IFoo의 메소드 foo를 재정의하지 않으면 foo.foo();Bar의 foo () 구현을 호출하지 않습니다.

Bar가 public void foo() throws InterruptedExceptionIFoo를 재정의 하려면 IFoo의 메소드 서명을 public void foo()추가해야합니다 throws InterruptedException. 그러나 foo () 메소드의 서명이 IFoo의 메소드 서명과 다르기 때문에 Foo 클래스에 문제가 발생합니다. 또한 throws InterruptedExceptionFoo의 메소드 foo ()에 추가 하면 Foo의 메소드 foo ()가 InterruptedException을 throw하지만 InterruptedException을 throw하지 않는다고 선언하는 또 다른 오류가 발생합니다.

보시다시피 (이 물건을 설명하는 데 괜찮은 일을했다면) InterruptedException과 같은 확인 된 예외를 겪고 있다는 사실은 인터페이스 IFoo를 구현 중 하나에 묶어 강제로 IFoo를 방해합니다. 다른 구현들!

이것이 확인 된 예외가 BAD 인 이유 중 하나입니다. 모자에.

한 가지 해결책은 확인 된 예외를 캡처하여 확인되지 않은 예외로 랩핑하고 확인되지 않은 예외를 처리하는 것입니다.


2
네, 잡으려고하지 않는다고 말해서 나빠요. 그러나 IFOO의 서명에 영향을 미치지 않도록하려면해야합니다. 예외를 포착하지 않기 위해 (예외가 BAD이기 때문에) 모든 인터페이스 서명을 재조정하는 대신 오히려 그렇게하고 계속 진행합니다.
살바도르 발렌시아

예, 동의합니다. 나는 무언가에 대해 조금 불분명했다. 예외가 전파되기를 원하므로 다른 곳에서 처리 할 수 ​​있습니다. 한 가지 해결책은 InterruptedException을 포착하고 검사되지 않은 예외를 발생시키는 것입니다. 즉, 우리는 검사 된 예외를 피하고 검사되지 않은 예외 (래퍼로만 이해되는 경우에도)를 통과합니다
Blueriver

"그러나 foo () 메소드의 서명이 IFoo의 메소드 서명과 다르기 때문에 Foo 클래스에 문제가 발생합니다." 방금 아이디어를 테스트 throws InterruptedException했으며 구현에 아무것도 던지지 않고 IFoo의 메소드 서명을 추가하더라도 컴파일 할 수 있습니다 . 따라서 실제로 아무런 문제가 발생하지 않습니다. 인터페이스에서 모든 메소드 시그니처 throw Exception를 작성하면 구현에서 예외 (모든 예외를 Exception캡슐화하는 예외)를 발생 시키거나 발생시키지 않을 수 있습니다.
Flyout91

그러나 나는 당신이 그러한 인터페이스를 구현하고 "구현되지 않은 메소드 추가"와 같은 것을 클릭 throw Exception할 때 구현이 아무것도 던지지 않을 수도 있지만 서명 의 절을 사용하여 자동으로 생성되기 때문에 혼란 스러울 수 있음을 인정 합니다. 보다 구체적인 예외. 그러나 여전히 인터페이스의 메소드에 대해 항상 예외를 던지는 것이 좋은 습관이라고 생각합니다. 다시 말해 사용자에게 아무것도 던지거나 던지지 않도록 선택할 수 있기 때문입니다.
Flyout91

이것은 전체 요점을 그리워합니다. 인터페이스의 목적은 고객이 만족해야하는 계약을 선언하는 것입니다. 여기에는 처리 할 수있는 실패 시나리오가 포함될 수 있습니다. 구현에 오류가 발생하면 해당 오류를 클라이언트 인터페이스에서 선언 한 적절한 추상 실패에 매핑해야합니다.
erickson

3
  • Java는 두 가지 예외 범주 (체크 및 체크되지 않음)를 구분합니다.
  • Java는 점검 된 예외에 대한 catch 또는 선언 된 요구 사항을 강제합니다.
  • 예외 유형에 따라 예외가 확인되는지 여부가 결정됩니다.
  • subclasses클래스의 직간접적인 모든 예외 유형 RuntimeException 은 검사되지 않은 예외입니다.
  • 클래스에서 상속 받지만 로 간주 Exception되지 않는 모든 클래스 .RuntimeExceptionchecked exceptions
  • Error 클래스에서 상속 된 클래스는 선택하지 않은 것으로 간주됩니다.
  • 컴파일러는 각 메소드 호출 및 감속을 검사하여 메소드가 발생하는지 여부를 판별합니다 checked exception.
    • 그렇다면 컴파일러는 예외가 포착되거나 throws 절에 선언되어 있는지 확인합니다.
  • catch-or-declare 요구 사항의 선언 부분을 충족시키기 위해 예외를 생성하는 메서드 throws는를 포함 하는 절을 제공해야 합니다 checked-exception.
  • Exception 클래스는 catch 또는 선언하기에 충분히 중요하다고 간주 될 때 점검되도록 정의됩니다.

2

다음은 결정에 도움이되는 간단한 규칙입니다. Java에서 인터페이스가 사용되는 방식과 관련이 있습니다.

클래스를 가져 와서 인터페이스가 클래스의 기능을 설명하지만 기본 구현은 (인터페이스처럼) 설명하지 않도록 인터페이스를 디자인한다고 상상해보십시오. 다른 방법으로 클래스를 구현할 수 있다고 가정하십시오.

인터페이스의 메소드를보고 예외를 고려하십시오.

기본 구현에 관계없이 메서드에서 예외를 throw 할 수있는 경우 (즉, 기능 만 설명) 인터페이스에서 확인 된 예외 여야합니다.

기본 구현으로 인해 예외가 발생한 경우 인터페이스에 없어야합니다. 따라서 클래스에서 검사되지 않은 예외 (인터페이스 서명에 검사되지 않은 예외가 표시 될 필요가 없기 때문에)이거나 랩핑하여 인터페이스 메소드의 일부인 검사 된 예외로 다시 발생시켜야합니다.

랩핑하고 다시 던질 지 여부를 결정하려면 인터페이스 사용자가 예외 조건을 즉시 처리해야하는지 또는 예외가 너무 일반적으로 발생하여 처리 할 수있는 조치가 없는지 다시 고려해야합니다. 스택을 전파하십시오. 랩핑 된 예외는 사용자가 정의하고있는 새로운 인터페이스의 기능으로 표현 될 때 의미가 있거나 다른 방법에도 발생할 수있는 가능한 오류 조건이있는 캐리어입니까? 전자의 경우 여전히 점검 된 예외 일 수 있으며, 그렇지 않은 경우 선택 해제해야합니다.

일반적으로 "버블 업"예외 (캐치 및 재 투입)를 계획하지 않아야합니다. 호출자가 예외를 처리하거나 (이 경우 확인) 상위 레벨 핸들러까지 올라 가야합니다 (이 경우 선택 해제하면 가장 쉬움).


2

코드에서 확인 된 예외를 던지고 catch가 몇 수준 이상이면 catch와 catch 사이의 각 메소드 서명에 예외를 선언해야합니다. 따라서 throw 경로의 모든 함수가 해당 예외에 대한 세부 정보를 알아야하므로 캡슐화가 중단됩니다.


2

간단히 말해서, 런타임 동안 위의 모듈이 처리해야하는 예외를 검사 예외라고합니다. 다른 하나는 RuntimeException또는 검사되지 않은 예외입니다 Error.

이 비디오에서는 Java의 확인 및 확인되지 않은 예외에 대해 설명합니다.
https://www.youtube.com/watch?v=ue2pOqLaArw


1

그것들은 모두 예외를 점검합니다. 점검되지 않은 예외는 RuntimeException의 서브 클래스입니다. 결정은 처리 방법이 아니라 코드에서 처리해야합니다. 컴파일러에서 예외를 처리하지 않았다고 알려주지 않게하려면 검사되지 않은 (RuntimeException의 서브 클래스) 예외를 사용합니다. 메모리 부족 오류 등과 같이 복구 할 수없는 상황에 대비해 저장해야합니다.


음 NumberFormatException이 확인 된 예외 인 경우 런타임 예외에서 상속 된다는 사실과 모순되지 않습니까?
eis

죄송하지만 명확하지 않았습니다. NumberFormatException이 아닌 FileNotFoundException을 참조하고있었습니다. 그의 # 2 & # 4에 따르면, 그는 Checked vs. Unchecked가 예외를 잡은 후 어떻게 처리했는지에 기초한 것으로 생각되었습니다. 어떻게 정의되지 않았습니다.
mamboking

-1

확인 된 예외를 싫어하는 또 다른 증거가있는 사람이 있다면 인기있는 JSON 라이브러리의 처음 몇 단락을 참조하십시오.

"이것은 확인 된 예외이지만 복구가 거의 불가능합니다. 대부분의 호출자는이 예외를 확인되지 않은 예외로 싸서 다시 던져야합니다."

그렇다면 왜 우리가 대신 "간단하게 포장"해야한다면 왜 누군가가 개발자가 예외를 계속 확인하게할까요? lol

http://developer.android.com/reference/org/json/JSONException.html


4
모든 발신자가 아닌 대부분의 발신자이므로 랩하고 다시 던져야합니다. 예외가 확인되었다는 사실은 호출자가 "가장 큰"호출자 중 하나인지 또는 예외를 처리 할 수 ​​있고 처리해야하는 소수의 것인지 생각해야한다는 것을 의미합니다.
Warren Dew

1
호출 할 때마다 오류를 확인하려면 C로 돌아가십시오. 예외는 코드를 오염시키지 않고 정상적인 프로그램 실행을 비정상과 분리하는 방법입니다. 예외 는 특정 레벨에서 자동으로 오류를 무시할 수 없도록 합니다 .
Slawomir

-1

확인 된 예외 :

  • 런타임시 프로그램의 원활한 실행을 위해 컴파일러가 확인하는 예외를 Checked Exception이라고합니다.

  • 컴파일 타임에 발생합니다.

  • 이것들이 올바르게 처리되지 않으면 컴파일 타임 에러가 발생합니다 (예외 아님).
  • RuntimeException을 제외한 Exception 클래스의 모든 서브 클래스는 Checked Exception입니다.

    가상의 예 -시험을 위해 집을 떠나고 있다고 가정하지만, 홀 티켓을 집에서 가져 왔는지 (컴파일 타임) 확인하면 Exam Hall (런타임)에 아무런 문제가 없습니다.

확인되지 않은 예외 :

  • 컴파일러에서 확인하지 않은 예외를 검사되지 않은 예외라고합니다.

  • 이들은 런타임에 발생합니다.

  • 이러한 예외가 제대로 처리되지 않으면 컴파일 시간 오류가 발생하지 않습니다. 그러나 프로그램은 런타임에 조기 종료됩니다.

  • RunTimeException 및 Error의 모든 하위 클래스는 검사되지 않은 예외입니다.

    가설의 예 -시험장에 있지만 학교에서 그 당시에는 아무것도 할 수 없지만 사전에 예방 조치를 취할 수있는 화재 사고 (런타임에 의미)가 있다고 가정합니다 (컴파일 시간).


-2

모든 예외는 확인 된 예외 여야합니다.

  1. 확인되지 않은 예외는 제한이 없습니다. 그리고 무제한 고 토스는 나쁜 것으로 간주됩니다.

  2. 확인되지 않은 예외는 캡슐화를 중단합니다. 그것들을 올바르게 처리하려면, 던지기와 포수 사이의 콜 트리에있는 모든 기능을 버그를 피하기 위해 알고 있어야합니다.

  3. 예외는 오류를 발생시키는 함수의 오류이지만 오류를 처리하는 함수의 오류는 아닙니다. 예외의 목적은 프로그램이 다른 컨텍스트에 대한 오류인지 아닌지에 대한 결정을 연기하여 프로그램에 두 번째 기회를 제공하는 것입니다. 다른 맥락에서만 올바른 결정을 내릴 수 있습니다.

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