[ 자바의 정석 Chapter8. 예외처리(Exception Handling) - 연습문제 ]
8-1. 예외처리의 정의와 목적에 대해서 설명하시오.
(1) 예외처리의 정의
- 사용자의 잘못된 조작 또는 개발자의 잘못된 코딩으로 인해 발생하는 프로그램 오류를 대비한 코드를 작성하는 것
(2) 예외처리의 목적
- 예외 상황이 발생했을 때 프로그램을 종료하지 않고 정상 실행 상태가 유지될 수 있도록 하기 위해
8-2. 다음은 실행 중 예외가 발생하여 화면에 출력된 내용이다. 이에 대한 설명 중 옳지 않은 것은?
java.lang.ArithmeticException : / by zero
at ExceprionEx18. method2(ExceptionEx18.java : 12)
at ExceprionEx18. method1(ExceptionEx18.java : 8)
at ExceprionEx18. main(ExceptionEx18.java : 4)
a. 위의 내용으로 예외가 발생했을 당시 호출스택에 존재했던 메서드를 알 수 있다.
b. 예외가 발생한 위치는 method2 메소드이며, ExceptionEx18.java 파일의 12번째 줄이다.
c. 발생한 예외는 ArithmeticException이며, 0으로 나누어서 예외가 발생했다.
d. method2메소드가 method1메소드를 호출하였고 그 위치는 ExceptionEx18.java파일의 8번째 줄이다.
☞ 예외의 종류는 java.lang.ArithmeticException에서 알 수 있듯이 'ArithmeticException' 산술연산의 예외가 발생했다. 예외의 원인은 / by zero에서 알 수 있듯이 0으로 나눗셈을 했기 때문이다.
at ExceprionEx18. method2(ExceptionEx18.java : 12)
at ExceprionEx18. method1(ExceptionEx18.java : 8)
at ExceprionEx18. main(ExceptionEx18.java : 4)
으로 확인해볼 수 있는데, 제일 아래 main 메소드에서 method1 메소드를 호출하였고, method1 메소드에서 method2를 호출했는데, method2의 이 때 ExceptionEx18.java 파일의12번째 줄에서 예외가 발생했다.
8-3. 다음 중 오버라이딩이 잘못된 것은? (모두 고르시오)
void add(int a, int b)
throw 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{}
☞ 오버라이딩 정의
- 부모 클래스에게 상속받은 메소드를 자식 클래스에서 재정의하는 것
☞ 오버라이딩 방법
- 부모 클래스와 시그니처(리턴 타입, 메소드 이름, 매개 변수 목록)가 동일해야 한다.
- 상속받은 메소드의 접근 제어자보다 더 넓은 범위로 접근 제어자를 선언할 수 없다.
- 새로운 예외를 throws 할 수 없다.
☞ void add(int a, intb) throw InvalidNumberException, NotANumberException{} 에서는 예외에 대해 InvalidNumberException과 NotANumberException 으로 던짐을 명시하고 있다. 그런데, NumberException은 이 둘이 상속받은 부모 클래스이고, 그 위로 Exception 클래스가 존재하고 있다. 그런데 오버라이딩은 하위 클래스에서 상위 클래스보다 더 많은 수의 예외를 선언할 수 없기 때문에 더 넓은 범위로 던짐을 명시할 수 없기 때문에 Exception과 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) {}
☞ catch(Exception e)는 최상위 예외처리 블럭이기 때문에 제일 마지막에 위치해야 한다.
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);
}
}
☞
1
3
5
1
2
5
6
☞ if(b) throw new ArithmeticException(); 에서 if 값이 true일 때 ArithmeticException으로 던져지고, ArithmeticException은 RuntimeException의 자손이므로 catch(RuntimeException e)에서 처리가 된다. 때문에 3이 출력되고 return을 만나 식을 빠져나가게 되는데, 이 때 fianlly는 실행이 되기 때문에 5가 출력된다.
☞ if(b) throw new ArithmeticException(); 에서 if 값이 false일 때 ArithmeticException으로 던져지지 않기 때문에 아래의 2가 출력된다. 그리고 처리해야 할 예외 상황이 없기 때문에 fianlly가 실행되어 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.prinltn(2);
}
finally
{
System.out.println(3);
}
}
static method2()
{
throw new NullPointerException();
}
}
☞ NullPointerException : 인스턴스(객체)가 제대로 생성되지 않았을 때의 예외 상황
☞
3
5
☞ 메인 메소드에서 method1을 호출했고, method1에서 method2를 호출했다. method2에서 NullPointerException이 발생했는데 method2에는 이 예외를 처리해줄 try~catch 블럭이 없기 때문에 method2는 종료되고 method1으로 돌아가게 된다. 그런데 method1에도 NullPointerException을 처리할 try~catch 블럭이 없기 때문에 method1은 종료되고, finally가 실행되어 3이 출력된다. method1까지 종료되어 메인 메소드로 돌아가게 되고 메인 메소드에는 NullPointerException에 대한 처리가 가능한 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
☞ 메인 메소드에서 method를 true의 값으로 호출했고, try 블럭에 들어가 1이 출력된다. 그리고 if(b) System.exit(0); 를 만나고 if의 값은 true이기 때문에 System.exit(0);가 실행되는데 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 Exercuse8_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;
}
}
while(true);
}
}
- 실행결과
1과 100사이의 값을 입력하세요 :50
더 작은 수를 입력하세요.
1과 100사이의 값을 입력하세요 :asdf
유효하지 않은 값입니다. 다시 값을 입력해주세요.
1과 100사이의 값을 입력하세요 :25
더 큰 수를 입력하세요.
1과 100사이의 값을 입력하세요 :38
더큰 수를 입력하세요.
1과 100사이의 값을 입력하세요 :44
맞췄습니다.
시도횟수는 5번입니다.
☞
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사이의 값을 입력하세요 :");
try
{
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 + "번입니다.");
}
}
catch(InputMismatchException ie)
{
System.out.println("유효하지 않은 값입니다. 다시 입력하세요.");
continue;
}
while(true);
}
}
}
☞ do~while문 안에 try~catch 블럭을 넣어서 발생하게 될 예외상황에 대한 처리를 해준다. 이 때 입력한 수가 데이터 형과 맞지 않을 때 예외를 처리해주는 'InputMismatchException' 을 사용한다. 유효하지 않은 값에 대한 출력문을 실행하고 continue를 만나 다시 돌아가게 한다.
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)
☞
import java.util.*;
class UnsupportedFuctionException extends RuntimeException
{
private final int ERR_CODE;
UnsupportedFuctionException(Stirng message)
{
this(message, 100);
}
UnsupportedFuctionException(String message, int errCode)
{
super(message);
this.ERR_CODE = errCode;
}
public int getErrorCode()
{
return ERR_CODE;
}
public String getMessage()
{
return "[" + getErrCode() : "]" + super.getMessage();
}
}
class Exercise8_9
{
public static void main(String[] args) throws Exception
{
throw new UnsupportedFuctionException("지원하지 않는 기능입니다." , 100);
}
}
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
☞ 메인 메소드에서 method1을 호출했고, method1에서 method2를 호출했다. method2에서 NullPointerException을 처리할 try~catch 블럭이 없기 때문에 method2는 종료되고 method1으로 돌아가게 된다. method1에는 NullPointerException을 처리할 블럭이 있기 때문에 2가 출력되고 throw e에 의해 e가 다시 던져졌지만 method1에는 이를 처리할 try~catch문이 더 이상 존재하지 않기 때문에 메인 메소드로 예외가 던져진다. 이 때 fianlly가 실행되어 4가 출력된다. 메인 메소드에는 던져진 예외를 처리할 try~catch 블럭이 존재하기 때문에 7이 출력되고 식이 종료된다.
'Java > Day23' 카테고리의 다른 글
| [Java] 자바의 정석 Chapter7. 객체지향 프로그래밍2 - 연습문제 (0) | 2021.11.29 |
|---|