예외처리
1. 예외와 오류
- 예외(Exception) : 프로그램에 존재하는 오류(error)를 의미, 개발자가 직접 처리할 수 있는 간단한 문제
- 에러(Error) : 개발자가 처리할 수 없는 복잡한 문제
2. 예외처리 (Exception Handling)
- 예외가 발생했을 때 이를 적절히 처리하여 프로그램이 비정상적으로 종료되는 것을 박는 방법
3. 예외 처리의 목적
- 발생한 문제로 인해 프로그램이 비정상적으로 종료되는 것을 막고, 사용자에게 발생한 문제에 대한 정보를 전달 하기 위함
- 예시
1) 예외 처리를 하지 않았을 경우
int a = 0;
int b = 2;
int c = b/a;
// by Zero at Test.main이라는 에러가 발생한다.
2) 예외 처리를 했을 경우
// 출력 : 0으로 나눌 수 없습니다. -> 해당 예제문은 다음 부분에 다룸
4. 고전적인 예외 처리 문제점
- 어떤 문제가 발생할 지 예상할 수 있어야 대비 가능
- 어떤 문제가 발생할 지 예상해도 대비할 수가 없음
- 프로그램의 규모가 커빌수록 모든 문제를 대비하기 힘듦
- 예시
Scanner input = new Scanner(System.in);
// 정수가 아닌 값을 입력(실수나 문자 등)하면 문제가 발생
System.out.println("제수를 입력하세요 >>>>")
int a = input.nextInt();
System.out.println("피제수를 입력하세요 >>>>")
int b = input.nextInt();
// 프로그램의 규모가 커질수록 작성할 코드가 길어짐
if (b == 0)
System.out.println("0으로 나누는 것은 불가능합니다.");
else
System.out.println(a + "/" + b + " = " + (a/b));
5. 자바에서의 예외 처리
- 자바에서 예외는 Exception이라는 클래스 객체로 동작
- 예외 클래스들도 서로 상속의 관계로 묶여져 있음
- 문제가 발생할 시 자동으로 해당 문제의 예외 인스턴스가 발생
6. 런타임 예외의 종류
- 프로그래밍 버그 혹은 논리의 오류
- Error + RuntimeException = Unchecked exception
<표>
7. 예외 처리 방식 : try-catch
(1) 모든 예외를 처리하는 방식
try{
코드 작성 영역
}catch(Exception e){
예외 발생시 처리 영역
}
- 예시
try{
System.out.print("제수를 입력 하세요 >>>> ");
int a = input.nextInt();
System.out.print("피제수를 입력 하세요 >>>> ");
int b = input.nextInt();
System.out.print(a/b);
}
catch (Exception e){
System.out.println("예외가 발생했습니다.");
}
// 0으로 나눌때 -> 출력 : 예외가 발생했습니다.
// 정수를 입력하지않고 문자열 입력시 -> 출력 : 예외가 발생했습니다.
(2) 특정 예외만 처리하는 방식
- 0으로 나누려고 하는 경우 -> 0 으로 나눌 수 없습니다.
- 정수가 아닌 값을 입력할 경우 -> 정수만 입력할 수 있습니다.
- 예외는 순서대로 except처리
try{
코드 작성 영역
} catch(예외1){
예외1 발생시 처리하는 영역
} catch(예외2){
예외1이 발생하지 않았고, 예외2 발생시 처리 영역
}
try {
System.out.print("제수를 입력하세요 >>> ");
int a = input.nextInt();
System.out.print("피제수를 입력하세요 >>> ");
int b = input.nextInt();
System.out.println(a/b);
}
catch (ArithmeticException e){
System.out.println("0으로 나눌 수 없습니다.");
}
catch (InputMismatchException e){
System.out.println("정수만 입력이 가능합니다.");
}
(3) 예외 처리 방식 : try-catch-finally
- 오류가 발생하든 하지 않든 간에 무조건 실행되는 구문
try{
코드 작성 영역
}
catch(예외1){
예외1 발생시 처리 영역
}
catch(예외2){
예외1이 발생하지 않았고,
예외2 발생시 처리 영역
}
finally{
예외 여부와 관계없이 실행되는 영역
}
Scanner input = new Scanner(System.in);
try{
System.out.print("제수를 입력하세요 >>> ");
int a = input.nextInt();
System.out.print("피제수를 입력하세요 >>> ");
int b = input.nextInt();
System.out.println(a/b);
}
catch(ArithmeticException e){
System.out.prinln("0으로 나눌 수 없습니다.");
}
catch(InputMismatchException e){
System.out.println("정수만 입력이 가능합니다.");
}
finally{
System.out.println("시스템 종료");
}
(4) 예외 메시지 처리하기
- catch문의 객체 참조 변수 e를 통해 예외 메시지를 받아 오기
- Sytem.err.println(); 구문을 통해 에러가 났을 경우 에러 메세지 출력하기
catch(Exception e){
System.out.println(e);
System.err.println();
}
8. 다형성과 예외
- 다형식의 원칙에 따라 상위 클래스의 참조 변수는 하위 클래스의 객체를 참조할 수 있음
try{
getInput(); // 예외를 발생하는 메소드
}
catch(NumberException e){
// NumberException의 하위 클래스를 모두 잡을 수 있음
}
try{
getInput(); // 예외를 발생하는 메소드
}
catch(Exception e){
// Exception의 하위 클래스를 모두 잡을 수 있으나 예외를 분간할 수 없음
}
try{
getInput(); // 예외를 발생하는 메소드
}
catch(NumberException e){
// 모든 NumberException이 잡힌다.
}
catch(TooSmallException e){
// 아무것도 잡히지 않는다.
}
9. 자동 리소스 닫기(try-with-resources)
- 자바 7이상 버전부터 사용 가능한 기능으로, 예외 발생 여부와 상관없이 사용했던 리소스 객체의 close()메소드를 호출해줌
- 각종 입출력 스트림, 서버 소켓 등 사용자가 직접 작성하지 않아도 자동으로 리소스를 닫아주어 안정성과 관리면에서 효율적임
- try-with-resources를 사용하기 위해서는 리소스 객체가 java.lang.AutoCloseable 인터페이스를 구현하고 있어야 함
- AutoCloseable 인터페이스에는 close() 메소드가 정의되어 있고, try-with-resources가 자동으로 호출함
10. 강제로 예외 발생시키기(throw)
- 자바에서는 예외로 인식하지 못하지만 프로그램 구현에서 예외가 발생할 때 사용
- 예외 클래스의 인스턴스를 생성한 다음 throw 키워드를 사용하여 예외를 발생 시킴
- 예외 메시지는 Exception 클래스의 생성자에 전달
Exception e = new Exception("Exception");
throw e; // 예외 발생
try{
Exception e = new Exception("고의 예외");
throw e;
}
catch(Exception e){
System.out.println("예외 발생");
System.out.println(e);
System.out.println(e.getMessage());
}
11. 예외 던지기(throws)
- 예외가 발생했을 경우 현재 메소드가 예외를 처리하지 않고 자신을 호출한 쪽으로 예외 처리에 대한 책임을 넘기는 것
- 예외를 넘겨받은 쪽은 반드시 직접 예외처리를 하거나 자신도 예외를 던져야 함
void method() throws Exception{
}
public class Test{
public static void mrthodA() throws Exception{
methodB();
}
public static void mrthodB() throws Exception{
methodC();
}
public static void mrthodC() throws Exception{
Exception e = new Exception();
throw e;
}
public Static void main(String[] args){
int age = -19;
try {
methodA();
}
catch(Exception e){
System.out.println("메인에서 처리");
}
}
}
12. 사용자 예외 클래스
- 예외 클래스를 직접 만들어서 사용
- Exception 클래스를 상속받은 클래스를 새로 생성
- Exception 클래스의 생성자에 message를 전달
class 예외 클래스 Extends Exception{
public 예외클래스(){}
public 예외클래스(String message){
super()('예외 메세지');
}
}
class AgeException exception{
public AgeException(){
}
public AgeException(String message){
super(message);
}
}
public class Test{
public static void ticketing(int age) throws AgeException {
if(age < 0){
throw new AgeException("나이 입력이 잘못 되었습니다.");
}
}
public static void main(String[] args){
int age = 19;
try {
ticketing(age);
}
catch(AgeException e){
e.printStackTrace();
}
}
}