[Java] 20. 예외 처리(1)

Java / / 2019. 4. 17. 19:57

1. 자바에서 매우 중요한 예외

자바에서는 예외라는 것이 있습니다. 예외를 모르면 자바를 모르는 것과 같다고 생각해도 됩니다. 자바에서는 예상과 다르게 동작을 하는 예외적인 일이 발생하게 되면 "예외"라는 것을 던져버립니다. 가장 일반적인 예가 null인 객체에 메소드를 호출한다든지, 5개의 공간을 가지는 배열을 만들어 6번째 값을 읽으라고 하는지 등의 경우가 있습니다.

 

2. try-catch는 짝이다

가장 일반적인 예로 설명한 배열 범위 밖의 값을 읽으려고 할 떄를 살펴보겠습니다. 

 

package c.exception;

public class ExceptionSample {

    public static void main(String[] args) {
        ExceptionSample sample = new ExceptionSample();
        sample.arrayOutOfBounds();
    }

    public void arrayOutOfBounds() {
        int[] intArray = new int[5];
        System.out.println(intArray[5]);
    }
}

 

arrayOutOfBounds()라는 메소드에서는 5개의 공간을 가지는 int 타입의 intArray라는 이름을 갖는 1차원 배열입니다. 그 다음 라인에서는 intArray 배열의 6번째 값을 출력합니다. 컴파일을 해보면 ArrayIndexOutOfBoundsException 이라는 것이 발생했습니다. 이는 배열의 범위 밖에 있는 위치를 요청한 예외라는 의미입니다. 

 

실행 결과1

그 다음 줄 부터는 at으로 시작하는 스택 호출 추적(call stack trace) 문장들이 출력됩니다. 이 호출 관계의 가장 윗줄에는 예외가 발생한 클래스와 메소드 이름과 줄의 번호를 출력합니다. 그 아래에는 그 메소드를 호출한 클래스와 메소드의 이름 및 줄의 번호가 출력됩니다. 이제 arrayOutOfBounds() 메소드를 다음과 같이 변경 합시다.

 

package c.exception;

public class ExceptionSample {

    public static void main(String[] args) {
        ExceptionSample sample = new ExceptionSample();
        sample.arrayOutOfBounds();
    }

    public void arrayOutOfBounds() {

        try {
            int[] intArray = new int[5];
            System.out.println(intArray[5]);
        } catch(Exception e) {

        }
    }
}

 

try를 쓰고 중괄호로 감싸고, catch라고 쓰고 메소드를 호출하는 것처럼 소괄호 안에 Exception이라는 클래스 이름과 매개 변수 이름 같은 e라는 것을 써줍니다. 그 다음엔 아무것도 하지는 않았지만 중괄호로 묶어주었습니다. 방금 추가한 것이 예외를 처리하는 "try-catch 블록"이라는 것 입니다. try 뒤에 중괄호로 예외가 발생하는 문장들을 묶어 주고, catch 괄호 안에 예외가 발생 했을 때 처리를 해줍니다. 이 예제처럼 반드시 모든 문장을 묶어줄 필요는 없고, 예외가 발생하는 부분만 묶어주면 됩니다. try 블록 안에서 예외가 발생되면 그 이하의 문장을 실행되지 않고 바로 catch블록으로 넘어갑니다. 

 

package c.exception;

public class ExceptionSample {
	public static void main(String[] args) {
		ExceptionSample sample = new ExceptionSample();
		sample.arrayOutOfBounds();
	}
	
	public void arrayOutOfBounds() {
		int[] intArray = new int[5];
		try {			
			System.out.println(intArray[5]);
		} catch(Exception e) {
			System.out.println("Exception occurred");
		}
		System.out.println("This code should run.");
	}
}

 

● try-catch에서 예외가 발생하지 않을 경우

    - try 내에 있는 모든 문장이 실행되고 try-catch 문장 이후의 내용이 실행된다.

 

● try-catch에서 예외가 발생하는 경우

    - try 내에서 예외가 발생한 이후의 문장들은 실행되지 않습니다. catch 내에 있는 문장은 반드시 실행되고, try-catch 문장 이후의 내용이 실행된다.

 

3. try-catch를 사용면서 처음에 적응하기 힘든 변수 선언

try-catch를 사용할 때 가장 하기 쉬운 실수가 바로 변수의 지정입니다. try 블록은 말 그대로 중괄호로 쌓여 있는 블록입니다. 그래서, try 블록 내에서 선언한 변수를 catch에서 사용할 수 없습니다. 밑의 코드와 같이 수정하고 컴파일을 하면 catch에서는 intArray가 누군지 모릅니다. 그래서 "canon find sysbol"이라는 에러와 함께 intArray가 누군지 모르겠다는 메시지가 출력됩니다.

 

package c.exception;

public class ExceptionSample {
	public static void main(String[] args) {
		ExceptionSample sample = new ExceptionSample();
		sample.arrayOutOfBounds();
	}
	
	public void arrayOutOfBounds() {
		try {
			int[] intArray = new int[5];
			System.out.println(intArray[5]);
		} catch(Exception e) {
			System.out.println(intArray.length);
		}
		System.out.println("This code should run.");
	}
}

 

그래서 이런 문제를 해결하기 위해서 일반적으로 catch 문장에서 사용할 변수에 대해서는 try 앞에 미리 선언해둡니다.

 

package c.exception;

public class ExceptionSample {

    public static void main(String[] args) {
        ExceptionSample sample = new ExceptionSample();
        sample.arrayOutOfBounds();
    }

    public void arrayOutOfBounds() {
    	int[] intArray = null;
        try {
            intArray = new int[5];
            System.out.println(intArray[5]);
        } catch(Exception e) {
        	System.out.println(intArray.length);
        }
        System.out.println("This code should run.");
    }
}
5
this code should run.

 

위의 코드를 보면 intArray가 null인데 catch 블록에서 길이를 5로 출력합니다. 예외가 발생하여 catch 블록이 실행된다고 해서 try 블록 내에서 실행된 모든 문장이 무시되는 것은 전혀 아닙니다. 이 예제에서는 intArray[5]를 호출하는 순간 예외가 발생합니다. 따라서 그 앞에 실행된 intArray의 크기를 5로 지정한 문장은 전혀 문제가 없습니다. 따라서, 반드시 catch에서 사용하는 변수는 try 블록 앞에 선언해야 한다는 것을 잊으면 안됩니다.

 

4. finally는 무슨 일이 생겨도 반드시 실행

try-catch 구문에 추가로 붙을 수 있는 블록이 하나 더 있습니다. 바로 finally 입니다. 자바에서 예외를 처리할 떄의 finally는 "어떠한 경우에도 넌 반드시 실행해!"라는 의미입니다. finallySample() 메소드를 만듭시다.

 

package c.exception;

public class ExceptionSample {

    public static void main(String[] args) {
        ExceptionSample sample = new ExceptionSample();
        sample.finallySample();
    }

    public void arrayOutOfBounds() {
    	int[] intArray = null;
        try {
            intArray = new int[5];
            System.out.println(intArray[5]);
        } catch(Exception e) {
        	System.out.println(intArray.length);
        }
        System.out.println("This code should run.");
    }
    
    public void finallySample() {
    	int[] intArray = new int[5];
    	try {
    		System.out.println(intArray[5]);
    	} catch(Exception e) {
    		System.out.println(intArray.length);
    	} finally {
    		System.out.println("Here is finally");
    	}
    	System.out.println("This code should run.");
    }
}

결과는 다음과 같습니다.

 

5
Here is finally
This code should run.

 

예외가 발생한 후 catch 블록이 실행되고, finally 블록이 실행된 후 try-catch 이후의 문장이 실행된 것을 알 수 있습니다. finally 블록은 코드의 중복을 피하기 위해서 반드시 필요합니다.

'Java' 카테고리의 다른 글

[Java] 20. 예외 처리(3)  (0) 2019.04.18
[Java] 20. 예외 처리(2)  (0) 2019.04.18
[Java] 19. 중첩 클래스(Nested Class)  (0) 2019.04.11
[Java] 18. enum 클래스  (0) 2019.04.09
[Java] 17. 상속과 final  (0) 2019.04.08
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기