- 예외를 처리하는 방법 : try-catch문 (직접 처리), 예외 선언하기(자신을 호출한 곳에 예외 처리 떠넘기기) - 메서드가 호출시 발생 가능한 예외를 호출하는 쪽에 알리는 것
구조
public void 메서드명() throws Exception1, Exception2, ..., ExceptionN {
// 메서드 내용
}
예시
public class SimpleExceptionExample {
public static void divide(int a, int b) throws ArithmeticException {
System.out.println(a + " / " + b + " = " + (a / b));
}
public static void main(String[] args) {
try {
divide(10, 0);
} catch (ArithmeticException e) {
System.out.println("오류 발생: " + e.getMessage());
}
}
}
divide 메서드는 ArithmeticException 발생시 메인 메서드 에서예외 처리를 한다.
- 자바에서 예외 명시
Unchecked Exceptions (RuntimeException 및 그 하위 클래스) Checked Exceptions (Exception 클래스와 그 하위 클래스 중 RuntimeException을 제외한 모든 예외)
메서드 선언 시 throws 키워드 뒤에 명시해야 하는 예외는 Checked Exceptions이다. Unchecked Exceptions는 자율
예시
import java.io.FileReader;
import java.io.IOException;
public class CheckedExceptionExample {
public static void readFile(String filename) throws IOException {
FileReader reader = new FileReader(filename);
// 파일 읽기 로직...
reader.close();
}
public static void main(String[] args) {
try {
readFile("example.txt");
} catch (IOException e) {
System.out.println("파일 읽기 오류: " + e.getMessage());
}
}
}
IOException은 Checked Exception이다.
readFile 메서드는 IOException을 throws로 선언한다.
이 메서드를 호출하는 쪽에서는 반드시 이 예외를 처리해야 한다.(try-catch 또는 다시 throws).
반면, RuntimeException (예: ArithmeticException, NullPointerException)은 명시적으로 선언하지 않아도 된다.
이렇게 Checked Exception을 명시적으로 선언하게 함으로써, 자바는 개발자가 예외 상황을 인식하고 적절히 처리하도록 강제한다.
8-12 메서드에 예외 선언하기 - 예제 1
public class Ex8_9 {
public static void main(String[] args) throws Exception {
method1(); // 같은 클르새내의 stati 멤버이므로 객체 생성 없이 직접 호출가능
} // 메인 메서드끝
static void method1() throws Exception{
method2();
} // method1 끝
static void method2() throws Exception{
throw new Exception();
} // method2 끝
}
호출 스택 그림
메인 메서드가 예외를 처리하지 않고 JVM으로 전달합니다 (throws Exception).
이로 인해 프로그램이 비정상적으로 종료됩니다.
JVM은 처리되지 않은 예외를 감지하고 기본 예외 처리기를 실행합니다.
이 기본 예외 처리기는 예외의 스택 트레이스를 콘솔에 출력합니다.
이건 예외가 처리 된 것이 아니다. 처리하려면 try - catch 문이 필요하다.
8-13 메서드에 예외 선언하기 - 예제 2
import java.io.File;
public class Ex8_10 {
public static void main(String[] args) {
try{
File file = createFile(""); //예외발생
System.out.println( file.getName()+ "파일이 성공적으로 생성되었습니다.");
}catch (Exception e){
System.out.println(e.getMessage()+" 다시 입력해 주시기 바랍니다.");
}
}
static File createFile(String fileName) throws Exception{
if(fileName ==null || fileName.equals(""))
throw new Exception("파일 이름이 유효하지 않습니다");
File f = new File(fileName);
f.createNewFile();
return f;
}
}
출력 결과
import java.io.File;
public class Ex8_10 {
public static void main(String[] args) {
try{
File file = createFile("바질토마토.txt"); //예외발생 x
System.out.println( file.getName()+ "파일이 성공적으로 생성되었습니다.");
}catch (Exception e){
System.out.println(e.getMessage()+" 다시 입력해 주시기 바랍니다.");
}
}
static File createFile(String fileName) throws Exception{
if(fileName ==null || fileName.equals(""))
throw new Exception("파일 이름이 유효하지 않습니다");
File f = new File(fileName);
f.createNewFile();
return f;
}
}
예외 선언하지 않고 메서드 안에서 예외 처리 하기
import java.io.File;
import java.io.IOException;
public class Ex8_10 {
public static void main(String[] args) {
File file = createFile("");
if (file != null) {
System.out.println(file.getName() + " 파일이 성공적으로 생성되었습니다.");
}
}
static File createFile(String fileName) {
File f = null;
try {
if (fileName == null || fileName.equals(""))
throw new IllegalArgumentException("파일 이름이 유효하지 않습니다");
f = new File(fileName);
f.createNewFile();
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage() + " 다시 입력해 주시기 바랍니다.");
} catch (IOException e) {
System.out.println("파일 생성 중 오류가 발생했습니다: " + e.getMessage());
}
return f;
}
}
8-14 finally 블럭
- 예외 발생 여부와 관계없이 수행되어야 하는 코드를 넣는다
try {
// 예외가 발생할 수 있는 코드
} catch (예외타입1 e) {
// 예외타입1에 대한 처리
} catch (예외타입2 e) {
// 예외타입2에 대한 처리
} finally {
// 예외 발생 여부와 관계없이 항상 실행되는 코드
}
finally 블록은 리소스 정리나 로그 기록 등 항상 실행되어야 하는 코드에 사용딘다. 예외가 발생하든 하지 않든, 심지어 try 블록 내에서 return문이 실행되더라도 finally 블록은 반드시 실행된다.