[8-1] 예외처리의 정의와 목적에 대해서 설명하시오.
답
정의 : 프로그램 실행 중에 발생할 수 있는 예외적인 상황(오류)을 처리하는 방법
목적 :
- 프로그램의 비정상 종료 방지
- 오류 원인 파악 및 디버깅 용이
- 정확한 오류 처리 및 복구
참고
예외 : 프로그램이 정상적으로 실행되는 것을 방해하는 예상치 못한 사건이나 오류
[8-2] 다음은 실행 도중 예외가 발생하여 화면에 출력된 내용이다. 이에 대한 설명 중 옳지 않은 것은?
java.lang.ArithmeticException : / by zero
at ExceptionEx18.method2(ExceptionEx18.java:12)
at ExceptionEx18.method1(ExceptionEx18.java:8)
at ExceptionEx18.main(ExceptionEx18.java:4)
① 위의 내용으로 예외가 발생했을 당시 호출스택에 존재했던 메서드를 알 수 있다.
② 예외가 발생한 위치는 method2 메서드이며, ExceptionEx18.java 파일의 12번째 줄이다.
③ 발생한 예외는 ArithmeticException이며, 0으로 나눠어서 예외가 발생했다.
④ method2메서드가 method1메서드를 호출하였고 그 위치는 ExceptionEx18.java파일의 8번째 줄이다.
답
4
풀이 : 에러로 확인 가능한 메서드 호출순서
ExceptionEx18.main(ExceptionEx18.java:4)
↓
ExceptionEx18.method1(ExceptionEx18.java:8)
↓
ExceptionEx18.method2(ExceptionEx18.java:12)
[8-3] 다음 중 오버라이딩이 잘못된 것은? (모두 고르시오)
void add(int a, int b)
throws InvalidNumberException, NotANumberException {}
class NumberException extends Exception {}
class InvalidNumberException extends NumberException {}
class NotANumberException extends NumberException {}
a.void add(int a, int b) throws InvalidNumberException, NotANumberException {}
b. void add(int a, int b) throws InvalidNumberException {}
c. void add(int a, int b) throws NotANumberException {}
d. void add(int a, int b) throws Exception {}
e. void add(int a, int b) throws NumberException {}
답
d,e
풀이
d. void add(int a, int b) throws Exception {}
상위 클래스 메서드와 동일한 시그니처를 가지고 있지만, 더 상위 클래스 예외를 던짐 (Exception은 NumberException의 상위 클래스).
잘못된 오버라이딩.
e. void add(int a, int b) throws NumberException {}
상위 클래스 메서드와 동일한 시그니처를 가지고 있지만, 더 상위 클래스 예외를 던짐 (NumberException은 InvalidNumberException과 NotANumberException의 상위 클래스).
잘못된 오버라이딩.
----------------------------
a. void add(int a, int b) throws InvalidNumberException, NotANumberException {}
상위 클래스 메서드와 동일한 시그니처와 예외를 던짐.
올바른 오버라이딩.
b. void add(int a, int b) throws InvalidNumberException {}
상위 클래스 메서드와 동일한 시그니처를 가지고 있고, 던지는 예외가 더 적음.
올바른 오버라이딩.
c. void add(int a, int b) throws NotANumberException {}
상위 클래스 메서드와 동일한 시그니처를 가지고 있고, 던지는 예외가 더 적음.
올바른 오버라이딩.
참고
오버라이딩 : 상위 클래스의 메서드를 하위 클래스에서 재정의하는 것
오버라이딩 시 주의
1. 메서드 이름: 상위 클래스와 동일해야 한다.
2. 매개변수 목록: 상위 클래스의 메서드와 동일야 한다.
3. 리턴 타입: 상위 클래스의 메서드와 동일야 한다.
4. 접근 제어자: 상위 클래스의 메서드보다 더 제한적인 접근 제어자를 사용할 수 없다.
5. 예외: 상위 클래스의 메서드가 던지는 예외와 같거나, 그 예외의 하위 클래스만을 던질 수 있다.
[8-4] 다음과 같은 메서드가 있을 때, 예외를 잘못 처리한 것은? (모두 고르시오)
void method() throws InvalidNumberException, NotANumberException {}
class NumberException extends RuntimeException {}
class InvalidNumberException extends NumberException {}
class NotANumberException extends NumberException {}
a. try {method( );} catch(Exception e) { }
b. try {method( );} catch(NumberException e) { } catch(Exception e) { }
c. try {method( );} catch(Exception e) { } catch(NumberException e) { }
d. try {method( );} catch(InvalidNumberException e){
} catch(NotANumberException e) { }
e. try {method( );} catch(NumberException e) { }
f. try {method( );} catch(RuntimeException e) { }
답
c
풀이
c. try {method();} catch(Exception e) { } catch(NumberException e) { }
Exception이 NumberException보다 상위 클래스이므로 Exception이 먼저 잡히면 NumberException은 절대로 실행되지 않음. 잘못된 예외 처리.
----------------------------
a. try {method();} catch(Exception e) { }
Exception은 모든 예외를 포괄하므로 올바른 예외 처리.
b. try {method();} catch(NumberException e) { } catch(Exception e) { }
NumberException이 Exception보다 구체적이므로 올바른 예외 처리.
d. try {method();} catch(InvalidNumberException e) { } catch(NotANumberException e) { }
InvalidNumberException과 NotANumberException은 각각 구체적인 예외이므로 올바른 예외 처리.
e. try {method();} catch(NumberException e) { }
NumberException은 InvalidNumberException과 NotANumberException의 상위 클래스이므로 올바른 예외 처리.
f. try {method();} catch(RuntimeException e) { }
RuntimeException은 NumberException의 상위 클래스이므로 올바른 예외 처리.
[8-5] 아래의 코드가 수행되었을 때의 실행결과를 적으시오.
class Exercise8_5 {
static void method(boolean b) {
try {
System.out.println(1);
if (b)
throw new ArithmeticException();
System.out.println(2);
} catch (RuntimeException r) {
System.out.println(3);
return;
} catch (Exception e) {
System.out.println(4);
return;
} finally {
System.out.println(5);
}
System.out.println(6);
}
public static void main(String[] args) {
method(true);
method(false);
} // main
}
답
1
3
5
1
2
5
6
Process finished with exit code 0
풀이 : 메서드 로직 처리 흐름
// 메서드 `method` 흐름
1. try 블록
System.out.println(1);이 실행됨
b가 true이면 throw new ArithmeticException();이 실행되어 ArithmeticException이 던져짐
b가 false이면 System.out.println(2);이 실행됨
2. catch 블록
RuntimeException 또는 그 하위 클래스의 예외가 발생하면 첫 번째 catch 블록이 실행됨
System.out.println(3);이 실행되고 return;으로 인해 메서드가 종료됨
Exception 또는 그 하위 클래스의 예외가 발생하면 두 번째 catch 블록이 실행됨
System.out.println(4);이 실행되고 return;으로 인해 메서드가 종료됨
3. finally 블록
예외 발생 여부와 상관없이 finally 블록은 항상 실행됨
System.out.println(5);가 실행됨
4. try-catch-finally 블록 외부의 코드
System.out.println(6);은 catch 블록이 아닌 정상적인 실행 흐름으로 try 블록을 빠져나갈 때만 실행됨
----------------------------
5. method(true) 실행 시
System.out.println(1); 출력
throw new ArithmeticException();로 인해 RuntimeException 발생
첫 번째 catch 블록이 실행되고 System.out.println(3); 출력
return;으로 인해 메서드가 종료되기 전에 finally 블록이 실행되어 System.out.println(5); 출력
메서드 종료
-> 1, 3, 5 출력
6. method(false) 실행 시
System.out.println(1); 출력
if (b) 조건이 false이므로 System.out.println(2); 출력
try 블록이 정상적으로 종료되면서 finally 블록이 실행되고 System.out.println(5); 출력
try-catch-finally 블록 외부의 코드 System.out.println(6); 출력
-> 1, 2, 5, 6 출력
[8-6] 아래의 코드가 수행되었을 때의 실행결과를 적으시오.
class Exercise8_6 {
public static void main(String[] args) {
try {
method1();
} catch (Exception e) {
System.out.println(5);
}
}
static void method1() {
try {
method2();
System.out.println(1);
} catch (ArithmeticException e) {
System.out.println(2);
} finally {
System.out.println(3);
}
System.out.println(4);
}
static void method2() {
throw new NullPointerException();
}
}
답
3
5
Process finished with exit code 0
풀이
1. method1 호출
2. method2 호출
3. method2에서 NullPointerException 발생
4. method1의 finally 블록 실행 (System.out.println(3);)
5. NullPointerException이 main 메서드로 전달
6. main 메서드의 catch 블록 실행 (System.out.println(5);)
[8-7] 아래의 코드가 수행되었을 때의 실행결과를 적으시오.
class Exercise8_7 {
static void method(boolean b) {
try {
System.out.println(1);
if (b)
System.exit(0);
System.out.println(2);
} catch (RuntimeException r) {
System.out.println(3);
return;
} catch (Exception e) {
System.out.println(4);
return;
} finally {
System.out.println(5);
}
System.out.println(6);
}
public static void main(String[] args) {
method(true);
method(false);
} // main
}
답
1
Process finished with exit code 0
풀이 : System.exit(0) 이 실행되면 프로그램이 즉시 종료된다.
1. 첫 번째 호출: method(true)
System.out.println(1); 실행 → 출력: 1
if (b)에서 b가 true이므로 System.exit(0); 실행
프로그램이 즉시 종료됨, 이후의 코드는 실행되지 않음
2. 두 번째 호출: method(false)
첫 번째 호출에서 프로그램이 종료되므로 실행되지 않음
[8-8] 다음은 1~100사이의 숫자를 맞추는 게임을 실행하던 도중에 숫자가 아닌 영문자를 넣어서 발생한 예외이다. 예외처리를 해서 숫자가 아닌 값을 입력했을 때는 다시 입력을 받도록 보완하라.
1과 100사이의 값을 입력하세요 :50
더 작은 수를 입력하세요.
1과 100사이의 값을 입력하세요 :asdf
Exception in thread "main" java.util.InputMismatchException
at java.util.Scanner.throwFor(Scanner.java:819)
at java.util.Scanner.next(Scanner.java:1431)
at java.util.Scanner.nextInt(Scanner.java:2040)
at java.util.Scanner.nextInt(Scanner.java:2000)
at Exercise8_8.main(Exercise8_8.java:16)
import java.util.Scanner;
class Exercise8_8 {
public static void main(String[] args) {
// 1~100 사이의 임의의 값을 얻어서 answer에 저장한다.
int answer = (int) (Math.random() * 100) + 1;
int input = 0; // 사용자입력을 저장할 공간
int count = 0; // 시도횟수를 세기 위한 변수
do {
count++;
System.out.print("1과 100사이의 값을 입력하세요 :");
input = new Scanner(System.in).nextInt();
if (answer > input) {
System.out.println("더 큰 수를 입력하세요 .");
} else if (answer < input) {
System.out.println("더 작은 수를 입력하세요 .");
} else {
System.out.println("맞췄습니다 .");
System.out.println("시도횟수는 " + count + "번입니다 .");
break; // do-while문을 벗어난다
}
} while (true);
}
}
답
import java.util.InputMismatchException;
import java.util.Scanner;
class Exercise8_8 {
public static void main(String[] args) {
// 1~100 사이의 임의의 값을 얻어서 answer에 저장한다.
int answer = (int) (Math.random() * 100) + 1;
int input = 0; // 사용자입력을 저장할 공간
int count = 0; // 시도횟수를 세기 위한 변수
do {
count++;
System.out.print("1과 100사이의 값을 입력하세요 :");
try {
input = new Scanner(System.in).nextInt();
}catch (InputMismatchException e){
System.out.println("숫자를 입력하세요.");
continue;
}
if (answer > input) {
System.out.println("더 큰 수를 입력하세요 .");
} else if (answer < input) {
System.out.println("더 작은 수를 입력하세요 .");
} else {
System.out.println("맞췄습니다 .");
System.out.println("시도횟수는 " + count + "번입니다 .");
break; // do-while문을 벗어난다
}
} while (true);
}
}
풀이
InputMismatchException : 예상 입력 타입과 다른 경우 예외 발생
입력받는 부분에 예외처리가 필요하므로 try-catch 구문으로 묶고, 예외 메시지로 사용자에 경고.
continue를 사용해 roop의 처음으로 돌아가 다시 값을 입력받도록 함.
[8-9] 다음과 같은 조건의 예외클래스를 작성하고 테스트하시오.
[참고] 생성자는 실행결과를 보고 알맞게 작성해야한다.
클래스명:UnsupportedFuctionException
조상클래스명:RuntimeException
멤버변수:
이름:ERR_CODE
저장값:에러코드
타입:int
기본값:100
제어자:final private
메서드
1. 메서드명:getErrorCode
기능:에러코드(ERR_CODE)를 반환한다.
반환타입:int
매개변수:없음
제어자:public
2. 메서드명:getMessage
기능:메세지의 내용을 반환한다. (Exception클래스의 getMessage( )를 오버라이딩)
반환타입:String
매개변수:없음
제어자:public
답
public class Exercise8_9 {
public static void main(String[] args) throws Exception {
throw new UnsupportedFuctionException("지원하지 않는 기능입니다.", 100);
}
}
class UnsupportedFuctionException extends RuntimeException{
private final int ERR_CODE;
public UnsupportedFuctionException(String msg, int errCode) {
// 메시지를 조상 클래스 생성자로 전달
super(msg);
// 에러 코드를 인스턴스 변수에 저장
this.ERR_CODE = errCode;
}
public int getERR_CODE() {
return ERR_CODE;
}
@Override
public String getMessage() { // 조상 클래스의 메서드 재정의
return "["+ERR_CODE+"]"+super.getMessage();
}
}
참고 : 호출 순서
new UnsupportedFunctionException("지원하지 않는 기능입니다.", 100)
↓
UnsupportedFunctionException 생성자 호출
↓
super(msg) 호출
↓
RuntimeException 생성자 실행 (this.message = message)
↓
this.ERR_CODE = errCode 실행 (ERR_CODE 필드 초기화)
[8-10] 예외처리의 정의와 목적에 대해서 설명하시오.
class Exercise8_10 {
public static void main(String[] args) {
try {
method1();
System.out.println(6);
} catch (Exception e) {
System.out.println(7);
}
}
static void method1() throws Exception {
try {
method2();
System.out.println(1);
} catch (NullPointerException e) {
System.out.println(2);
throw e;
} catch (Exception e) {
System.out.println(3);
} finally {
System.out.println(4);
}
System.out.println(5);
}
static void method2() {
throw new NullPointerException();
}
}
답
2
4
7
Process finished with exit code 0
풀이
main 메서드가 method1을 호출합니다.
main 메서드의 try 블록 시작
↓
method1 메서드가 method2를 호출합니다.
method1의 try 블록 시작
↓
method2 메서드가 NullPointerException을 던집니다.
NullPointerException 발생
↓
method1의 첫 번째 catch 블록에서 NullPointerException을 잡습니다.
System.out.println(2); 실행 → 출력: 2
throw e; 실행하여 예외를 다시 던짐.
↓
finally 블록이 실행됩니다.
System.out.println(4); 실행 → 출력: 4
↓
method1 메서드가 예외를 던지기 때문에 System.out.println(5);는 실행되지 않음.
↓
던져진 예외는 main 메서드의 catch 블록에서 잡힘.
System.out.println(7); 실행 → 출력: 7
'개념' 카테고리의 다른 글
[JAVA의 정석] Chapter10_연습문제 (0) | 2024.12.15 |
---|---|
[JAVA의 정석] Chapter09_연습문제 (0) | 2024.12.15 |
[JAVA의 정석] Chapter07_연습문제 (0) | 2024.12.10 |
[JAVA의 정석] Chapter06_연습문제 (1) | 2024.12.10 |
[JAVA의 정석] Chapter05_연습문제 (0) | 2024.12.08 |