프로그램이 어떤 원인에 의해 오작동하거나 비정상적으로 종료되는 경우가 있다. 이 결과를 초래하는 원인을 프로그램 에러 또는 오류라고 한다.
이를 발생 시점에 따라 '컴파일 에러'와 '런타임 에러'로 나눌 수 있다.
- 컴파일 에러 : 컴파일할 때 발생하는 에러.
- 런타임 에러 : 실행 시에 발생하는 에러.
컴파일러가 .java에 대해 오류가 없다면 .class파일을 생성하고 생성된 .class파일을 실행할 수 있게 되는 것이다.
하지만 컴파일을 마쳤다고 해서 실행 시에도 에러가 발생하지 않는 것은 아니다. 컴파일러는 실행 시 발생할 수 있는 잠재적인 오류까지 검사할 수 없다. 그래서 이런 런타임 에러를 방지하기 위해 모든 경우의 수를 고려하에 대비하는 것이 필요하다.
자바에서 실행 시 발생할 수 있는 오류를 '에러'와 '예외', 두 가지로 구분했다.
- 에러 : 프로그램 코드에 의해서 수습될 수 없는 심각한 오류 ( 메모리 부족, 스택오버플로우 등....)
- 예외 : 프로그램 코드에 의해서 수습될 수 있는 다소 미약한 오류
계층 구조
자바에서 실행 시 발생할 수 있는 오류를 클래스로 정의하였다. 모든 클래스의 조상이 Object클래스이므로 Exception클래스와 Error클래스 역시 Object클래스의 자손이다.
RuntimeException클래스들은 주로 프로그래머의 실수에 의해서 발생될 수 있는 예외들이다. 예를 들면, 배열의 범위가 벗어 나든가, null인 값을 참고 변수의 멤버로 호출하려 했다던가 하는 경우에 발생한다.
RuntimeException클래스들을 제외한 나머지 클래스들은 외부의 영향으로 발생할 수 있는 것들로서, 프로그램의 사용자들의 동작에 의해서 발생하는 경우가 많다. 예를 들면, 존재하지 않는 파일 이름을 적거나, 입력한 데이터 형식이 잘못되었던가 하는 경우이다.
(예외처리를 해주지 않으면 컴파일조차 되지 않는다.)
try-catch문
예외 처리의
정의 : 프로그램 실행 시 발생할 수 있는 예외에 대비한 코드를 작성하는 것.
목적 : 프로그램의 비정상 종료를 막고, 정상적인 실행상태를 유지하는 것.
try{
//예외가 발생할 가능성이 있는 문장들을 넣는다.
}catch(Exception1 e1){
//Exception1이 발생했을 경우, 이를 처리하기 위한 문장을 적는다.
}catch(Exception2 e2){
//Exception2이 발생했을 경우, 이를 처리하기 위한 문장을 적는다.
}catch(Exception3 e3){
//Exception3이 발생했을 경우, 이를 처리하기 위한 문장을 적는다.
}
▷ try 블록 내에서 예외가 발생한 경우
1. 발생한 예외와 일치하는 catch 블록이 있는지 확인한다.
2. 일치하는 catch블록을 찾게 되면, 그 catch블록 내의 문장들을 수행하고 전체 try-catch문을 빠져나가서 그다음 문장을 계속해서 수행한다. 만일 일치하는 catch블록을 찾지 못하면, 예외는 처리되지 못한다.
▷ try 블록 내에서 예외가 발생하지 않은 경우
1. catch블록을 거치지 않고 전체 try-catch문을 빠져나가서 수행을 계속한다.
public class ExceptionTest {
public static void main(String[] args) {
System.out.println(1);
System.out.println(2);
try{
System.out.println(3);
System.out.println(0/0); // ArithmeticException이 발생
System.out.println(5); // 실행되지 않는다.
}catch(ArithmeticException ae){
if(ae instanceof ArithmeticException) System.out.println("true");
System.out.println("ArithmeticException");
}catch(Exception e){ // ArithmeticException을 제외한 모든 예외가 처리
System.out.println("Exception");
}
System.out.println(6);
}
}
printStackTrace() : 예외 발생 당시의 호출 스택(Call Stack)에 있었던 메서드의 정보와 예외 메시지를 화면에 출력한다.
getMessage() : 발생한 예외 클래스의 인스턴스에 저장된 메시지를 얻을 수 있다.
예외 발생시키기
키워드 throw를 사용해서 프로그래머가 고의로 예외를 발생시킬 수 있다.
- 연산자 new를 이용해서 발생시키려는 예외 클래스의 객체를 만든 다음
- 키워드 throw를 이용해서 예외를 발생시킨다.
public class ExceptionTest {
public static void main(String[] args) {
try{
Exception e = new Exception("고의로 발생시켰음.");
throw e;
// throw new Exception("고의로 발생시켰음".); -> 한 줄로 줄일 수 있다.
}catch(Exception e){
System.out.println(e.getMessage());
e.printStackTrace();
}
}
}
메서드로 예외 선언하기
메서드의 선언부에 키워드 throws를 사용해서 메서드 내에서 발생할 수 있는 예외를 적어주기만 하면 된다, 그 예외가 여러 개일 경우 쉼표로 구분한다.
void method() throws Exception1, Exception2, ... ExceptionN{
//메서드의 내용
}
public class ExceptionTest {
public static void main(String[] args) {
for(int i = 0 ; i < 10; i++){
try{
calc(10,i);
}catch(ArithmeticException e){
System.out.println("0으로 나눌 수 없습니다.");
}
}
}
static void calc(int a, int b) throws ArithmeticException{
System.out.println(a/b);
}
}
calc() 메서드에서 발생할 가능성이 있는 예외를 throws로 처리한다. 그리고 clac() 메서드를 호출하는 main() 메서드에서 throws로 처리한 예외를 처리해주면 된다. 중요한 것은 호출한 메서드에서 예외를 처리하도록 하는 것이다.
finally블록
try{
// 예외가 발생할 가능성이 있는 문장들을 넣는다.
}catch(Exception e){
// 예외처리를 위한 문장을 적는다.
}finally{
//예외의 발생여부와 상관없이 항상 수행되어야 하는 문장들을 넣는다.
// finally 블럭은 try-catch문의 맨 마지막에 위치해야한다.
}
사용자 정의 예외 만들기
기존의 정의된 예외 클래스 외에 필요에 따라 새로운 예외 클래스를 정의하여 사용할 수 있다.
public class ExceptionTest {
public static void main(String[] args) {
try{
install();
}catch(SpaceExcetion e){
System.out.println(e.getMessage());
}finally{
System.out.println("설치를 종료합니다.");
}
}
static void install() throws SpaceExcetion{
if(!enoughMemory()) throw new SpaceExcetion("메모리가 부족합니다.");
}
static boolean enoughMemory(){
return false;
}
}
class SpaceExcetion extends Exception{
SpaceExcetion(String msg){
super(msg);
}
}
Exception 클래스를 상속받아서 SpaceException클래스를 만들었다. install() 메서드를 실행할 때 메모리가 부족하다고 하면 SpaceExcetion 예외가 수행된다.
이렇게 예외처리에 대해 간단하게 알아보았다. 이렇게 이론적으로 정리하는 것도 중요하지만 실무에서 사용할 수 있도록 하는 것이 가장 중요한 게 아닐까 싶다. 정리는 했지만 아직 예외 처리를 프로젝트에 적용하기에는 부족한 게 사실이다. 그래서 실제로 예외 처리가 적용된 사례를 보면서 공부를 하면 더 좋은 개발자로 성장할 수 있을 것 같다.
'Language > Java' 카테고리의 다른 글
[Java]스트림(stream)(2/3) (0) | 2022.06.07 |
---|---|
[Java]스트림(stream)(1/3) (0) | 2022.06.07 |
[Java] 람다식 (0) | 2022.06.06 |
객체 지향 프로그래밍에 대해 묻는다면 ? (0) | 2022.05.25 |
Java는 어떻게 동작하지?( + 메모리 영역) (0) | 2022.05.23 |