본문 바로가기
  • hello world
Language/Studying

[Java] Exception 예외처리

by JJoajjoa 2024. 7. 18.

 

에러 : 컴퓨터 하드웨어의 오작동 또는 고장으로 인해 응용 프로그램 실행 오류가 발생하는 것
예외 : 에러 이외에 사용자의 잘못된 조작 또는 개발자의 잘못된 코딩으로 인해 발생하는 프로그램 오류
         → 개발자가 해결할 수 있는 오류 ( == 오류 발생 시 차선책을 선택할 수 있는)

 

에러나 예외가 발생되면 프로그램이 종료됨

→ 예외는 예외처리를 통해 프로그램이 종료되지 않게, 정상 실행 상태를 유지하게 만들 수 있음

 

자바는 예외가 발생할 가능성이 높은 코드를 컴파일할 때 예외 처리 유무를 확인함

→ 만약 예외 처리 코드가 없다면 컴파일이 안됨

→ 하지만 모든 예외에 대해서 확인하는 것은 아님

 


자바에서는 예외를 클래스로 관리

JVM은 프로그램을 실행하는 도중에 예외가 발생하면 해당 예외 클래스로 객체를 생성 

→ 예외 처리 코드에서 예외 객체를 이용할 수 있도록 해줌

 

모든 예외 클래스는 java.lang.Exception 클래스를 상속받음

 

 

 

예외의 종류:

  • 일반예외 exception : 컴파일 전에 체크
    프로그램 실행 시 예외가 발생할 가능성이 높기 때문에 자바 소스코드를 컴파일하는 과정에서
    해당 예외 처리 코드가 있는지 검사 → 없다면 컴파일 오류 발생
    == 예외처리를 해주지 않으면 실행 자체가 불가능!
  • 실행예외 runtime exception : 실행할 때 체크
    실행 시 예측할 수 없이 갑자기 발생하기 때문에 컴파일하는 과정에서 예외 처리 코드가 있는지 검사하지 않음
    → 실행 중 실행예외가 생기면 프로그램 강제 종료!

 

 

일반예외 종류 :

  • InterruptedException
  • ClassNotFoundException
  • IOException
  • FileNotFoundException
  • CloneNotSupportedException

 

 

실행예외 종류 :

  • NullPointException
    객체 참조가 없는 상태, 즉 null 값을 갖는 참조변수로 객체 접근 연산자인 . 를 사용했을 때 발생
    == 객체가 없는 상태에서 객체를 사용하려해서 예외 발생
  • ArrayIndexOutOfBoundsException
    배열에서 인덱스 범위를 초과할 경우
  • NumberFormatException
    매개값인 문자열이 숫자로 변활될 수 없는 문자가 포함되어 있는 경우
  • ClassCastException
    타입 변환은 상위-하위 클래스 간에 발생하고 구현 클래스와 인터페이스 간에도 발생
    이러한 관계가 아니라면 클래스는 다른 타입으로 변환할 수 없기 때문에 발생
    == 다운캐스팅이 불가능한 상황에서 다운캐스팅을 시도할 때 발생
  • ArithmeticException
     연산 자체가 불가능할 때 발생(ex 분모가 0일 때)

 


 

예외 처리 구문이 있다면 JVM은 적절히 예외가 처리되었다고 판단하기 때문에 강제종료 되지 않음
심지어 구문 내에 어떤한 코드도 없어도 예외가 처리된 것으로 간주함

 

 

 

예외 처리

try - catch - finally 블록

생성자 내부와 메서드 내부에서 작성되어 일반 예외와 실행 예외가 발생할 경우, 예외 처리를 할 수 있도록 해줌

try {
	// 일반예외, 실행예외 발생 가능 코드
} catch (예외클래스명 참조변수명) { //다중catch가능
	// 예외가 발생했을 때 처리
} finally { //생략가능
	// 예외 발생과 상관없이 무조건 실행
}

 

 

예외 전가

throws 키워드

메소드 선언부 끝에 작성되어 메서드 작성되어 메서드에서 처리하지 않은 예외를 호출한 곳으로 떠넘기는 역할을 함 

→ 자신을 호출한 지점으로 예외를 전가시킴

→ 예외 처리의 의무를 호출한 메서드가 가지게 됨!

리턴타입 메서드명(입력매개변수) throws 예외클래스명 {
 	//예외발생코드
}

 

 

 

사용자 정의 예외 클래스

생성방법

  1. 예외클래스 직접 정의
  2. 작성한 예외클래스를 이용해 객체 생성
  3. 고려해야하는 상황에 예외 객체를 던짐(throws)

▼ 예외를 해당 메서드 안에서 직접 처리

void abc(int age) {
	try {
    	if (age >= 0)
        	System.out.println("정상값 출력");
        else
        	throws new MyException();
    } catch (MyException e) {
    	System.out.println("예외처리");
    }
}

void def() {
	abc(-2);
}

 

▼ 예외를 상위 메서드로 전가하여 예외 처리

void abc(int age) throws MyException {
	if (age >= 0)
        System.out.println("정상값 출력");
    else
        throws new MyException();
}

void def() {
	abc(-2);
    try {
    	abc(-2);
    } catch (MyException e) {
    	System.out.println("예외처리");
    }
}

 

 

 

예외클래스 메서드

▶ getMessage()

예외객체에 저장된 메세지를 반환

이 메시지에는 예외가 발생한 원인에 대한 간단한 설명을 포함하고 있음

예외 클래스의 생성자에서 설정할 수 있음

try {
    int result = 10 / 0;
} catch (ArithmeticException e) {
    System.out.println("예외 메시지: " + e.getMessage());
}
//Exception message: / by zero

 

public class CustomExceptionExample {
    public static void main(String[] args) {
        try {
            throw new Exception("Custom error message");
        } catch (Exception e) {
            System.out.println("Exception message: " + e.getMessage());
        }
    }
}
//Exception message: Custom error message

 

 

 

▶ printStackTrace()

 예외가 발생했을 때 호출 스택(Call Stack)의 정보를 출력

 예외가 발생한 시점의 메서드 호출 경로를 추적하여, 디버깅 시 매우 유용한 정보를 제공

public class ExceptionPrintStackTraceExample {
    public static void main(String[] args) {
        try {
            int[] numbers = {1, 2, 3};
            System.out.println(numbers[5]); // ArrayIndexOutOfBoundsException 발생
        } catch (ArrayIndexOutOfBoundsException e) {
            e.printStackTrace();
        }
    }
}
//java.lang.ArrayIndexOutOfBoundsException: 5
//    at ExceptionPrintStackTraceExample.main(ExceptionPrintStackTraceExample.java:5)

 

 


 

예시

 

public class ExceptionTest {

	public static void main(String[] args) {
//		print(-5);
		// 컴파일 오류
		// print 메서드가 throws절로 정의되어 있어서
		// 그 예외를 처리하지 않으면 컴파일이 안된다.
		// 어캐해야하는데
			// throws절로 처리하기
			// try~catch로 처리하기
		try {
			print(-5);
		} catch (Exception e) {
			
		} // 이런방식으로
	}

	private static void print(int count) throws Exception {
		if (count < 0) throw new Exception("음수는 안돼욧");
		for (int i = 0; i < count; i++) {
			System.out.println("hello");
		}
	}

}

 

 

▼ try catch

public class ExceptionTest {

	public static void main(String[] args) {
		methodA();
	}

	private static void methodA() {
		try {
			methodB();
		} catch (Exception e) {

		}
	}

	private static void methodB() throws Exception {
		int random = (int) (Math.random() * 10);
		if (random % 2 == 0)
			throw new Exception();
	}

}

 

▼ throws

public class ExceptionTest {

	public static void main(String[] args) throws Exception {
		methodA();
	}

	private static void methodA() throws Exception {
		methodB();
	}

	private static void methodB() throws Exception {
		int random = (int) (Math.random() * 10);
		if (random % 2 == 0)
			throw new Exception();
	}

}

 

▼ 사용자 정의

public class ExceptionTest {

	public static void main(String[] args) {
		try {
			print(-5);
		} catch (Exception e) { //Exception 객체를 참조하는 e
			System.out.println(e.getMessage());
		}
	}

	private static void print(int count) throws Exception {
		if (count < 0) throw new Exception("음수는 안돼욧"); //Exception 객체생성
		for (int i = 0; i < count; i++) {
			System.out.println("hello");
		}
	}

}

 

 

 

 

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class ExceptionTest {

	public static void main(String[] args) throws Exception {

		try {
			FileReader fr = new FileReader("list.txt");
			// 애초에 FileReader의 생성자가 throw절로 정의되어있어서
			// 이것을 호출하는 부분에도 예외처리를 해주어야한다
			BufferedReader br = new BufferedReader(fr);
			String line = br.readLine();
			while (line != null) {
				System.out.println(line);
				line = br.readLine();
			}
		} catch (FileNotFoundException e) {
			System.out.println("그런 파일은 없어용");
		} catch (IOException e) {
			
		}

	}

}

 

 

 

public class ExceptionTest {

	public static void main(String[] args) {
		try {
			System.out.println("start");
			print(5);
			System.out.println("after");
		} catch (Exception e) {
			System.out.println("catch");
			System.out.println(e.getMessage());
		} finally {
			System.out.println("finally");
		}
	}

	private static void print(int count) throws Exception {
		if (count < 0)
			throw new Exception("음수는 안돼욧");
		System.out.println("after if");
		for (int i = 0; i < count; i++) {
			System.out.println("hello");
		}
	}

}

 

 

 

 

 

 

▼ RuntimeException

public class ExceptionTest {

	public static void main(String[] args) {
		methodA();
	}

	private static void methodA() {
		try {
			methodB();
		} catch (RuntimeException e) {
			
		}
	}

	private static void methodB() throws RuntimeException {
		int random = (int) (Math.random() * 10);
		if (random % 2 == 0)
			throw new RuntimeException();
	}

}