” 유효한 자바 “에 있는 조슈아 블로흐는
복구 가능한 조건에 대해 확인 된 예외를 사용하고 프로그래밍 오류에 대해 런타임 예외를 사용하십시오 (제 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에서 언제 점검 된 예외를 작성해야하며 언제 런타임 예외 여야합니까?
답변
많은 사람들은 확인 된 예외 (즉, 명시 적으로 잡거나 다시 던져야하는 예외)를 전혀 사용해서는 안된다고 말합니다. 예를 들어 C #에서 제거되었으며 대부분의 언어에는 없습니다. 따라서 RuntimeException
(확인되지 않은 예외) 의 하위 클래스를 항상 던질 수 있습니다
그러나 확인 된 예외는 유용하다고 생각합니다.이 예외는 API 사용자에게 예외 상황 (복구 가능한 경우)을 처리하는 방법을 생각하도록 강요 할 때 사용됩니다. 확인 된 예외가 Java 플랫폼에서 과도하게 사용되어 사람들이 예외를 미워하게 만드는 것입니다.
특정 질문에 관해서는 :
-
는
NumberFormatException
체크 예외를 고려?
번호NumberFormatException
가 선택되어 있지 않습니다 (=는의 하위 클래스입니다RuntimeException
). 왜? 모르겠어요 (그러나 방법이 있어야했습니다isValidInteger(..)
) -
가
RuntimeException
체크되지 않은 예외?
그렇습니다. -
여기서 무엇을해야합니까?
이 코드의 위치와 수행하려는 작업에 따라 다릅니다. UI 계층에있는 경우이를 포착하고 경고를 표시하십시오. 그것이 서비스 계층에 있다면-전혀 잡지 마십시오-거품을 내십시오. 예외를 삼키지 마십시오. 대부분의 경우에 예외가 발생하면 다음 중 하나를 선택해야합니다.- 그것을 기록하고 반환
- 다시 던지십시오 (메서드에 의해 던져 질 것이라고 선언하십시오)
- 생성자에서 현재 예외를 전달하여 새 예외를 구성
-
이제 위의 코드도 검사 예외가 될 수 없습니까? 이런 상황을 복구하려고 할 수 있습니까? 할 수 있습니까?
그랬을 수도 있습니다. 그러나 확인되지 않은 예외를 잡는 데 방해가되는 것은 없습니다. -
사람들
Exception
이 throws 절에 클래스 를 추가하는 이유는 무엇 입니까?
사람들이 무엇을 잡아서 다시 던질지를 고려하기가 게으 르기 때문에 대부분의 경우 던지는Exception
것은 나쁜 습관이므로 피해야합니다.
아아, 잡을 때, 다시 던질 때, 사용할 때 및 확인되지 않은 예외를 사용할 때를 결정할 수있는 단일 규칙은 없습니다. 나는 이것이 많은 혼란과 나쁜 코드를 유발한다는 데 동의합니다. 일반적인 원칙은 Bloch가 명시합니다 (일부 인용). 그리고 일반적인 원칙은 처리 할 수있는 레이어에 예외를 다시 던지는 것입니다.
답변
무언가가 “체크 된 예외”인지 여부는 포착 여부 또는 catch 블록에서 수행하는 작업과 관련이 없습니다. 예외 클래스의 속성입니다. 의 서브 클래스를 아무거나 Exception
제외 에 RuntimeException
와 그 서브 클래스는 체크 예외입니다.
Java 컴파일러는 확인 된 예외를 포착하거나 메소드 서명에서이를 선언하도록합니다. 프로그램 안전성을 향상시켜야했지만 대다수의 의견은 그것이 생성하는 디자인 문제의 가치가 없다고 생각합니다.
왜 예외가 발생하게합니까? 핸들 오류가 빠를수록 좋습니다. 왜 거품이 일어 납니까?
즉, 전체이기 때문에 점 예외는. 이 가능성이 없으면 예외가 필요하지 않습니다. 이를 통해 원래 발생한 저수준 방법으로 오류를 처리하지 않고 선택한 수준에서 오류를 처리 할 수 있습니다.
답변
-
위의 사항은 확인 된 예외로 간주됩니까? 아니 당신이 예외를 처리하는 사실은 그것은하지 않습니다
Checked Exception
그것은 경우RuntimeException
. -
가
RuntimeException
은unchecked exception
? 예
Checked Exceptions
이다 subclasses
의 java.lang.Exception
Unchecked Exceptions
이다 subclasses
의java.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
오류가 발생하기 쉬운 코드의 도입 가능성을 방지하기 위해 명시 적으로.
답변
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
. 그러나 당신은 계약의 일부가 아닌 것과 같은 점검되지 않은 예외를 유지해야 할 필요는 없습니다.
답변
1) 아니요, NumberFormatException은 검사되지 않은 예외입니다. 체크하지 않았기 때문에 잡았더라도 (필요하지는 않습니다). 서브 클래스가의 서브 클래스이기 때문 IllegalArgumentException
입니다 RuntimeException
.
2) RuntimeException
확인되지 않은 모든 예외의 근본입니다. 의 모든 서브 클래스 RuntimeException
는 체크되지 않습니다. Throwable
오류를 제외한 다른 모든 예외 는 확인됩니다 (아래에 있음 Throwable
).
3/4) 존재하지 않는 파일을 선택했음을 사용자에게 알리고 새 파일을 요청할 수 있습니다. 또는 사용자에게 잘못된 것을 입력했다고 알리는 것을 종료하십시오.
5) 던지고 잡는 'Exception'
것은 나쁜 습관입니다. 그러나 더 일반적으로는 호출자가 처리 방법을 결정할 수 있도록 다른 예외를 처리 할 수 있습니다. 예를 들어, 일부 파일 입력 읽기를 처리하기 위해 라이브러리를 작성했고 메소드에 존재하지 않는 파일이 전달 된 경우이를 처리하는 방법을 모릅니다. 발신자가 다시 묻거나 종료 하시겠습니까? 따라서 예외를 호출자에게 다시 체인을 던집니다.
대부분의 경우 unchecked Exception
프로그래머가 입력을 확인하지 않았기 때문에 발생합니다 ( NumberFormatException
첫 번째 질문 의 경우 ). 그렇기 때문에 예외를 생성하지 않는 더 우아한 방법이 있기 때문에 선택 사항을 잡을 수 있습니다.
답변
확인 됨-발생하기 쉽습니다. 컴파일 시간에 체크인했습니다.
예 : 파일 작업
확인되지 않음-데이터가 잘못되었습니다. 런타임에 체크인했습니다.
예 :
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)
여기서 예외는 잘못된 데이터로 인한 것이며 컴파일 시간 동안 확인할 수 없습니다.
답변
확인 된 예외는 컴파일 타임에 JVM 및 리소스 (files / db / stream / socket 등)와 관련하여 확인됩니다. 확인 된 예외의 원인은 컴파일 타임에 리소스를 사용할 수없는 경우 응용 프로그램이 catch / finally 블록에서이를 처리하기위한 대체 동작을 정의해야한다는 것입니다.
검사되지 않은 예외는 순전히 프로그래밍 방식의 오류, 잘못된 계산, 널 데이터 또는 심지어 비즈니스 로직 장애로 인해 런타임 예외가 발생할 수 있습니다. 코드에서 검사되지 않은 예외를 처리 / 캐치하는 것이 좋습니다.