Java의 정석 : 3rd Edition, 2016을 개인 학습용으로 정리한 내용입니다.
"ppt 파일 자료, 연습문제"를 학습 용도로 배포할 수 있음을 고지하셨습니다.
저자님께 감사드립니다.
[8-1] 예외처리의 정의와 목적에 대해서 설명하시오.
나의 답 :
- 정의 : 프로그램을 실행할 때 발생할 수 있는 예외에 대비하는 코드를 작성하는 것
- 목적 : 프로그램의 비정상 종료를 막고, 정상적인 실행상태를 유지하기 위함.
예외처리(exception handling)란
- 정의 : 프로그램 실행 시 발생할 수 있는 예기치 못한 예외의 발생에 대비한 코드를 작성하는 것
- 목적 : 실행 중인 프로그램의 갑작스런 비정상 종료를 막고, 정상적인 실행상태를 유지할 수 있도록 함.
[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)
a. 위의 내용으로 예외가 발생했을 당시 호출스택에 존재했던 메서드를 알 수 있다.
b. 예외가 발생한 위치는 method2메서드이며, ExceptionEx18.java파일의 12번째 줄이다.
c. 발생한 예외는 ArithmeticException이며, 0으로 나누어서 예외가 발생했다.
d. method2메서드가 method1메서드를 호출하였고 그 위치는 ExceptionEx18.java파일의 8번째 줄이다.
d : method1()가 method2()를 호출함. (main → method1() → method2())
- method1() : method2()를 호출한 라인에서 예외 발생
- main() : method1()을 호출한 라인에서 예외 발생
[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 : Exception은 모든 예외의 조상이므로 자손에서 선언 불가 (조상 = 확장 가능(더 많은 수의 예외))
e : NumberException은 두 예외의 조상이므로 자손에서 선언 불가(조상 = 확장 가능(더 많은 수의 예외))
[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 : Exception(모든 예외의 조상)는 모든 예외를 처리할 수 있어 마지막 catch블럭에 선언해야 한다.
마지막 catch블럭에 선언하지 않으면, 컴파일 에러가 발생한다. (이후의 문장들이 무의미하기 때문)
[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
main() → method(true) : try{1}, ArithmeticException 발생 → catch(RuntimeException r){3} → finally{5} → 메서드 종료(return문)
main() → method(false) : try{1, 2} → finally{5} → 6
※ try블럭에서 예외가 발생하면 다음 문장은 수행되지 않고 실행 흐름이 catch블럭으로 이동되어 예외를 처리한다.
※ catch블럭은 발생한 예외에 해당하는 블럭 하나만 수행된 후 try-catch문을 벗어나게 된다.
※ finally블럭은 예외 발생 여부에 상관없이 항상 수행된다. (단, System.exit(0)으로 인해 프로그램 종료될 때는 수행X)
※ try/catch블럭에 return문이 있어도 finally블럭이 수행된 후에 메서드가 종료된다.
ArithmeticException는 RuntimeException의 자손이므로 RuntimeException가 선언된 catch블럭에서 처리된다.
[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
main() → method1() → method2() : NullPointerException 발생 → method1() : finally{3} → main() : catch(Exception e) {5}
- method2() : 예외를 처리할 try-catch블럭이 없으므로 method2()는 종료되고 이를 호출한 method1()으로 되돌아간다.
- method1() : NullPointerException을 처리할 catch블럭이 없으므로 method1()도 종료되고, 이를 호출한 main()로 돌아간다. 이 때 finally블럭이 수행되어 '3'이 출력된다.
- main() : 모든 예외를 처리할 수 있는 catch블럭(Exception)이 있으므로 예외가 처리되고 '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);
}
}
나의 답 :
1
main() → method(true) : try{1}, System.exit(0)(프로그램 종료 : 정상 종료이므로 예외 발생X)
변수 b의 값이 true이므로 System.exit(0); 수행되어 프로그램이 즉시 종료된다. 이 때는 finally블럭이 수행되지 않는다.
[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.*;
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); // 무한반복문
}
}
// 1과 100사이의 값을 입력하세요 :50
// 더 작은 수를 입력하세요.
// 1과 100사이의 값을 입력하세요 :asdf
// 유효하지 않은 값입니다. 다시 값을 입력해주세요.
// 1과 100사이의 값을 입력하세요 :25
// 더 큰 수를 입력하세요.
// 1과 100사이의 값을 입력하세요 :38
// 더 큰 수를 입력하세요.
// 1과 100사이의 값을 입력하세요 :44
// 맞췄습니다.
// 시도횟수는 5번입니다.
나의 답 :
사용자 입력을 받는 부분을 try-catch블럭안에 넣어 예외 처리한다.
에러 메시지를 보면 InputMismatchException예외가 발생했으므로 이를 선언한 catch블럭을 작성한 후
다른 예외도 발생할 수 있으므로 Exception을 선언한 catch블럭을 마지막에 넣었다.
do {
count++;
System.out.print("1과 100사이의 값을 입력하세요 : ");
try {
input = new Scanner(System.in).nextInt();
} catch (InputMismatchException e) {
System.out.println("유효하지 않은 값입니다. 다시 값을 입력해주세요.");
} catch (Exception e) {
System.out.println("유효하지 않은 값입니다. 다시 값을 입력해주세요.");
}
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); // 무한반복문
해설 :
화면으로부터 값을 입력받는 부분을 try-catch구문으로 예외처리 하면 된다.
※ 사용자로부터 값을 입력받는 경우에는 유효성검사를 철저하게 해야 한다. (사용자가 어떤 값을 입력할지 모르기 때문)
do {
count++;
System.out.print("1과 100사이의 값을 입력하세요 : ");
input = new Scanner(System.in).nextInt();
try {
input = new Scanner(System.in).nextInt();
} catch (Exception 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); // 무한반복문
[8-9] 다음과 같은 조건의 예외클래스를 작성하고 테스트하시오.
[참고] 생성자는 실행결과를 보고 알맞게 작성해야한다.
* 클래스명 : UnsupportedFuctionException
* 조상클래스명 : RuntimeException
* 멤버변수 :
이 름 : ERR_CODE
저장값 : 에러코드
타 입 : int
기본값 : 100
제어자 : final private
* 메서드 :
1. 메서드명 : getErrorCode
기 능 : 에러코드(ERR_CODE)를 반환한다.
반환타입 : int
매개변수 : 없음
제어자 : public
2. 메서드명 : getMessage
기 능 : 메세지의 내용을 반환한다.(Exception클래스의 getMessage()를 오버라이딩)
반환타입 : String
매개변수 : 없음
제어자 : public
class Exercise8_9 {
public static void main(String[] args) throws Exception {
throw new UnsupportedFuctionException("지원하지 않는 기능입니다.", 100);
}
}
Exception in thread "main" UnsupportedFuctionException: [100]지원하지 않는 기능입니다.
at Exercise8_9.main(Exercise8_9.java:5)
나의 답 :
- msg : 에러메시지를 저장하는 인스턴스 변수. 상속받은 것이므로 조상 생성자에서 초기화되도록 해야 한다.
- getMessage() : 조상으로부터 상속받은 메서드. ERR_CODE도 같이 출력되도록 하기 위해 오버라이딩했다.
msg가 조상 생성자에서 초기화되었으므로 super.getMessage()를 호출하여 예외 메시지를 얻어야 함.
※ main()에서 printStackTrace()를 호출하지 않았는데 에러 메시지 출력되는 이유
: JVM의 예외처리기가 getMessage()를 호출했기 때문, main()에서 처리되지 않은 예외는 JVM의 예외처리기가 처리함.
class UnsupportedFuctionException extends RuntimeException {
private final int ERR_CODE;
UnsupportedFuctionException(String msg, int errCode) {
super(msg); // RuntimeException(String msg) 호출
ERR_CODE = errCode;
}
UnsupportedFuctionException(String msg) {
this(msg, 100);
}
public int getErrCode() {
return ERR_CODE;
}
public String getMessage() { // Exception.getMessage() 오버라이딩
return "[" + getErrCode() + "]" + super.getMessage();
}
}
[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
main() → method1() → method2() : NullPointerException 발생 → method1() : catch(NullPointerException e) {2} → throw e → finally{4} → main() : catch(Exception e) {7}
- method2() : 예외를 처리할 try-catch블럭이 없으므로 method2()는 종료되고 이를 호출한 method1()으로 되돌아간다.
- method1() : catch블럭(NullPointerException)이 있으므로 예외 처리 되었으나, throw로 다시 발생시켰다.
예외가 발생한 catch블럭 내에 예외를 처리할 try-catch블럭이 없으므로 method1()가 종료되고, 이를 호출한 main()에 예외가 전달된다. finally블럭이 수행되어 '4'가 출력된다.
- main() : 모든 예외를 처리할 수 있는 catch블럭(Exception)이 있으므로 예외가 처리되고 '7'가 출력된다.
'Java의 정석 : 3rd Edition' 카테고리의 다른 글
[Java의 정석 - 연습문제] Chapter10. 날짜와 시간 & 형식화 (0) | 2023.05.11 |
---|---|
[Java의 정석 - 연습문제] Chapter09. java.lang패키지와 유용한 클래스 (0) | 2023.02.06 |
[Java의 정석 - 연습문제] Chapter07. 객체지향 프로그래밍 II(OOP) (2) | 2023.01.03 |
[Java의 정석 - 연습문제] Chapter06. 객체지향 프로그래밍 I(OOP) (0) | 2022.12.01 |
[Java의 정석 - 연습문제] Chapter05. 배열(Array) (0) | 2022.11.23 |