Part 11. 예외 처리

Hyunsu·2023년 2월 23일
0

국비 교육

목록 보기
16/36
post-thumbnail

📝 목차

  1. 프로그램 오류
  2. 예외 확인
  3. 예외 클래스 계층 구조
  4. Unchecked Exception
  5. 사용자 정의 예외
  6. 예외 처리 방법
  7. Exception 과 오버라이딩

1. 프로그램 오류

프로그램 수행 시 치명적 상황이 발생하여 비정상 종료 상황이 발생한 것으로 프로그램 에러라고도 한다.

오류의 종류

  • 컴파일 에러

프로그램의 실행을 막는 소스 코드상의 문법 에러로 소스 코드 수정으로 해결한다.

System.out.println 을 out.println 으로 작성하는 등
  • 런타임 에러

프로그램 실행 중 발생하는 에러로 주로 if 문 사용으로 에러를 처리한다. 배열의 인덱스 범위를 벗어났거나 계산식의 오류 등에서 발생한다.

if (num2 == 0) { 에러 처리 코드 }
  • 시스템 에러

컴퓨터 오작동으로 인한 에러로 소스 코드 수정으로 해결이 불가능하다.

인터넷 연결 불량 등

오류 해결 방법

소스 코드 수정으로 해결 할 수 있는 예측 가능한 에러를 예외 Exception 라고 하는데 이러한 예외 상황 구문을 처리 하는 방법인 예외 처리를 통해 해결한다.


2. 예외 확인

Java API Document 에서 해당 클래스에 대한 생성자나 메소드를 검색하면 그 메소드가 어떤 Exception 을 발생시킬 가능성이 있는지 확인 가능하다.
발생하는 예외를 미리 확인하여 상황에 따른 예외 처리 코드를 작성할 수 있다.

// java.io.BufferedReader 중 readLine() 메소드
// 키보드 입력을 효율적으로 읽어오는 객체로 Scanner 보다 기능은 부족하지만 속도가 빠름

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
public String readLine() throws IOException

Java 프로그램 실행 중 예를 들어 산술적 Exception 상황이 발생하면 해당 상황과 일치하는 예외 클래스 ArithmeticException 을 찾아서 new ArithmeticException 객체로 만들어 문제가 발생한 위치로 던진다.


3. 예외 클래스 계층 구조

Exception 과 Error 클래스 모두 Object 클래스의 자손이며 모든 예외의 최고 조상은 Exception 클래스이다.
Exception 은 반드시 예외 처리해야 하는 Checked Exception 과 해주지 않아도 되는 Unchecked Exception 으로 나뉜다.

Throwable : 던져질 수 있는 클래스의 공통점을 묶어 놓은 인터페이스

  • Error : 개발자가 코드로 예상할 수 없는 심각한 에러

  • Exception : 개발자가 코드로 예상할 수 있는 미약한 에러

    RuntimeException

    if 문으로 해결 가능한 Unchecked Exception 으로 가벼운 문제이므로 컴파일 단계에서 예외가 발생하지 않는다.

    // ArithmeticException
    5 / 0
    
    // IndexOutOfBoundsException
    int[] a = new int[3];
    int[5]; 
    
    // NullPointerException
    Car c = NULL;
    c.getWheel()

    Exception

    if 문으로 해결 불가능한 Checked Exception 으로 IOException 등 컴파일 단계에서 예외가 발생한다.


4. Unchecked Exception

RuntimeException 클래스

Unchecked Exception 이며 주로 프로그래머의 부주의로 인한 오류인 경우가 많으므로 예외 처리보다는 코드를 수정해야 하는 경우가 많다.

RuntimeException 후손 클래스

  • ArithmeticException

    0 으로 나누는 경우 발생하며 if 문으로 나누는 수가 0 인지 검사

  • NullPointerException

    Null 인 참조 변수로 객체 멤버 참조 시도 시 발생하며 객체 사용 전에 참조 변수가 null 인지 확인

  • NegativeArraySizeException

    배열 크기를 음수로 지정한 경우 발생하며 배열 크기를 0 보다 크게 지정해야 함

  • ArrayIndexOutOfBoundsException

    배열의 index 범위를 넘어서 참조하는 경우 배열명의 length 를 사용하여 배열의 범위 확인

  • ClassCastException

    객체의 형변환 시 객체 타입 변환이 적절하지 않을 시 발생하며 instanceof 연산자로 객체타입 확인 후 cast 연산

  • InputMismatchException

    Scanner 를 사용하여 데이터 입력 시 입력 받는 자료형이 불일치할 경우 발생


5. 사용자 정의 예외

Java API 에서 제공하는 Exception 클래스만으로는 처리할 수 없는 예외가 있을 경우 사용자의 필요에 의해 생성하는 Exception 클래스이다.
Exception 발생하는 곳에서 throw new 예외클래스명 ( ) 으로 발생시킨다.

public class UserException extends Exception {
	// 기본 생성자
	public UserException("입력한 점수 범위 초과") { }
    
    // 매개변수 생성자
    public UserException(String msg) { super(msg); }
}

public class UserExceptionController {
	public void method() throws UserException {
    	throw new UserException("사용자 정의 예외 발생");
    }
}

public class Run {
	public static void main(String[] args) {
		UserExceptionController uc = new UserExceptionController();

		try {
			uc.method();
		} catch (UserException e) {
			System.out.println(e.getMessage()); // 설정한 에러 메세지 출력
		}
	}
}

사용 방법

이미 존재하는 자바의 Exception Class 중 하나를 상속 받아서 관련성 있는 예외가 있으면 해당 예외 클래스를 없으면 Exception 또는 RuntimeException 을 상속 받는다.

Checked Exception 을 원할 경우 Exception 상속
Unchecked Exception 을 원할 경우 RuntimeException 상속


6. 예외 처리 방법

📌 Exception 이 발생한 곳에서 직접 처리

  • try : Exception 발생할 가능성이 있는 코드를 안에 기술
  • catch : try 구문에서 Exception 발생 시 해당하는 Exception 에 대한 처리 기술로 Exception 간의 상속 관계를 고려해야함
  • finally : Exception 발생 여부와 관계없이 꼭 처리해야 하는 로직 기술로 return 문을 만나도 실행되지만 System.exit(); 만나면 무조건 종료되며 자원 해제 역할
// 1) try catch 예외 처리
public void method() {
	BufferedReader br = null;
    
    try {
    	br = new BufferedReader(new InputStreamReader(System.in));
        
        System.out.print("입력 : ");
        String str = br.readLine();
        
        System.out.println("입력된 문자열 : " + str);
    } catch (IOException e) {
    	e.printStackTrace();
    }
}

// 2) try catch finally 예외 처리
public void method() {
	BufferedReader br = null;
    
    try {
    	br = new BufferedReader(new InputStreamReader(System.in));
        
        System.out.print("입력 : ");
        String str = br.readLine();
        
        System.out.println("입력된 문자열 : " + str);
    } catch (IOException e) {
    	e.printStackTrace();
    } finally {
    	try {
        	System.out.println("BufferedReader 반환");
            br.close();
        } catch (IOException e) {
        	e.printStackTrace();
        }
    }
}

상위 타입 예외를 매개변수로 작성하면 하위 타입의 예외를 모두 처리가 가능하다.
이 때 상위 타입 catch 를 뒤쪽에 배치해서 하위 타입 catch 에 대한 검사가 먼저 진행되게 해야 오류가 발생하지 않는다.

📌 Exception 처리를 호출한 메소드에게 위임

  • throw : 예외 강제 발생
  • throws : 메소드 선언 시 throws Exception 명을 추가해 호출한 상위 메소드에게 처리 위임

계속 위임하면 main ( ) 메소드까지 위임하게 되고 main ( ) 메소드에서도 처리되지 않는 경우 프로그램이 비정상 종료된다.

public static void main(String[] args) {
	ThrowsTest tt = new ThrowsTest();
    
    try {
    	tt.methodA(); // 최종적으로 IOException 받음
    } catch (IOException e) {
    	e.printStackTrace();
    } finally {
    	System.out.println("프로그램 종료");
    }
}

// throws 예외 처리
public void methodA() throws IOException {
	methodB();
}

public void methodB() throws IOException {
	methodC();
}

// methodC 에서 IOException 발생 시 호출한 곳으로 던지겠다는 의미
public void methodC() throws IOException {
	throw new IOException(); // IOException 강제 발생
}

7. Exception 과 오버라이딩

오버라이딩 시 throws 하는 Exception 의 개수와 상관없이 처리 범위가 같거나 후손이어야 한다.
즉 Exception 클래스는 상속이 될 수록 상위 클래스보다 예외의 내용이 더 상세하게 기술된다.

public class Parent {
	public void method() throws IOException { }
}

public class Child1 extends Parent {
	@Override
    public void method() throws EOFException { } // Exception 사용 시 부모이므로 오류
}

오버라이딩

상위 클래스로부터 상속 받은 메서드를 하위 클래스에서 재정의 하는 것

오버라이딩 성립 조건

  • 접근제한자는 같거나 더 넓은 범위
  • 예외처리 구문은 같거나 더 좁은 구체적 범위
profile
현수의 개발 저장소

0개의 댓글