본문 바로가기
JAVA

예외 처리

by 요리하다그만둠 2022. 5. 26.

-에러(Error)

: 하드웨어의 잘못된 동작 또는 고장으로 인한 오류

: 에러가 발생되면 프로그램 종료

: 정상 실행 상태로 돌아갈 수 없음

 

-예외(Exception)

: 사용자의 잘못된 조작 또는 개발자의 잘못된 코딩으로 인한 오류

: 예외가 발생되면 프로그램 종료

: 예외 처리 추가하면 정상 실행 상태로 돌아갈 수 있음

 

예외의 종류

: 일반(컴파일 체크) 예외(Exception)

-예외 처리 코드 없으면 컴파일 요류 발생

 

실행 예외(RuntimeException)

: 예외 처리 코드를 생략하더라도  컴파일이 되는 예외

: 경험 따라 예외 처리 코드 작성 필요함

 

public class JavaEx9 {

	public static void main(String[] args) {
		
		int num1 = 26;
		// int num2 = 0;
		int num2 = (int)((Math.random()*10)-1);
		int result = 0;
		
		
		try {
			 result = num1 / num2;
		} catch(Exception e) {
			// 메시징(messaging)
			System.out.println("err msg : " + e);
			System.out.println("err msg : " + e.getMessage());
			System.out.println("err msg : " + e.toString());
			// 처리(patch), 대용
			System.out.println("========================");
		}
		System.out.println(result);
	}

}

예외 처리를 할 때는 try/catch를 사용하며 cathc(Exception e)를 사용

위에 코드를 돌려서 오류가 나오면

이런 결과가 나옵니다.

시스템적으로 가르쳐 줄 수도 있고 System.out.prinln("0으로 나눈 오류 발생"); 이렇게 catch 구문에 코드를 넣어줄 수도 있습니다.

정상 작동이 되면 값만 나옵니다.

 

e.getMessage() 

- 에러의 원인을 간단하게 출력해 줍니다.

 

e.toString()

- 에러의 Exception 내용과 원인을 출력해줍니다.

 

pringStackTrace()

-예외 발생 코드 추적한 내용을 모두 콘솔에 출력합니다

- 프로그램 테스트하면서 오류 경로까지 가르쳐주어서 유용하게 활용할 수 있습니다.

 

NullPointerException

- 객체 참조가 없는 상태

- null 값 갖는 참조 변수로 객체 접근 연산자인 도트(.) 사용 시 발생

String data = null;
System.out.println(data.toString());
// data 변수는 null 값을 가지고 있기 때문에 String 객체를 참조하고 있지않다.
// 하지만 2라인에서 toString() 메소드를 호출하고 있어서 여기서 NUllPointerException이 발생한다.

 

ArraylndexOutOfBoundsException

- 배열에서 인덱스 범위를  초과하여 사용할 경우 실행 예외인 java.lang.ArratIndexOutOf-BoundsException이 발생한다.

 

ArraylndexOutOfBoundsException이 발생하는 이유는 실행 매개 값을 주지 않았기 때문이다.

[Run • Run Configurations ]를 선택 후 Arguments 텝에서 매개 값 2개를 넣어주면 예외가 발생하지 않는다.

 

NumberFormatException

-문자열을 숫자로 변환하는 코드입니다

 

변환 타입 메서드명(매개 변수) 설명
int integer.parseint(String s) 주어진 문자열을 정수로 변환해서 리턴
double Double.parseDouble(String s) 주어진 문자열을 실수로 변환해서 리턴

메서드를 매게 값인 문자열이 숫자로 변환될 수 있다면 숫자를 리턴 하지만,

숫자로 변환될 수 없는 문자가 포함되어 있다면 java.lang.NumberFormatException을 발생시킵니다.

NumberFormatException을 발생시켜보겠습니다.

public class NumberFormatExceptionExample {
	public static void main(String[] args) {
		String data1 = "100";
		String data2 = "a100";
		
		int value1 = Integer.parseInt(data1);
		int value2 = Integer.parseInt(data2); 
		// value2는 NumberFormatException이 발생될것임
		
		int result = value1 + value2;
		System.out.println(data1 + "+" + data2 + "=" + result);
	}
}

작동시켜보면

이렇게 출력됩니다.

data1 변수의 "100" 문자열은 숫자로 변환이 가능하기 때문에 정상 실행되지만 data2 변수에 "a100" 문자열은

숫자로 변환할 수 없기 때문에 다음과 같이 NumberFormatException 발생하게 됩니다.

 

ClassCastException

타입 변환(Casting)은 상위 클래스와 하위 클래스 간에 발생하고 구현 클래스와 인터페이스 간에도 발생합니다.

이러한 관계가 아니라면 클래스는 다른 클래스로 타입 변환할 수 없습니다. 억지로 타입 변환을 시도한 경우에

ClassCastException 이 발생합니다.

Animal 이라는 추상 클래스가 있고
Dog / Cat 라는 인터페이스가 존재할때

Animal 타입 변수에 대입된 객체가 Dog 이므로 다시 Dog 타입으로 변환하는 것은
아무런 문제가 없다.

Animal animal = new Dog();
Dog dog = (Dog) animal;

그러나
Animal animal = new Dog();
Cat cat = (Cat) animal;
다음과 같이 타입 변환을 하면 ClassCastException이 발생한다.
대입된 객체가 아닌 다른 클래스 타입으로 타입 변환을 했기 때문이다.

ClassCastException을 발생시키지 않으려면 타입 변환 전에 타입 변환이 가능한지

instanceof 연산자로 확인하는 것이 좋다.

instanceof 연산자의 결과가 true로 나오면 좌항 객체를 우항 타입으로 변환이 가능하다는 뜻이다.

Animal animal = new Dog();
if(animal instanceof Dog) {
  Dog dog = (Dog) animal;
  } else if (animal instanceof Cat) {
  Cat cat = (Cat) animal;
  }

 

public class ClassCastException {

	public static void main(String[] args) {

		Dog dog = new Dog();
		ChangeDog(dog);
		
		Cat cat = new Cat();
		ChangeDog(cat);
	}

	public static void ChangeDog(Animal animal) {
		//if(animal instanceof Dog) {
		//		Dog dog = (Dog) animal; // ClassCastException 발생 가능
		//	}
		
	}

}
class Animal{}
class Dog extends Animal {}
class Cat extends Animal {}

실행을 해보면

 

ClassCastException이 발생한다.  그 이유는 Cat 객체를 매개 값으로 주었기 때문에 Dog 타입으로 변환할 수 없습니다.

 

예외 처리 코드는

try - catct - finally 블록을 이용합니다.

블록은 생성자 내부와 메서드 내부에서 작성되어 일반 예외와 실행 예외가

발생할 경우 예외 처리를 할 수 있도록 해줍니다.

try {					위에서 아래로 실행 됩니다.

	// 예외 발생 가능 코드
    
    }catcg ( 예외클래스 e) {
    
    // 예외처리
    
    } finally {
    
 	   항상 실행;
    
    }

try 블록에는 예외 발생 가능 코드가 위치하고 예외 발생 없이 정상 실행이 되면 catch 블록의 코드는 실행되지 않고

finally 블록의 코드가 실행됩니다.

만약 try 블록의 코드에서 예외가 발생하면 즉시 실행을 멈추고 catch 블록으로 이동하여 예외 처리 코드를 실행합니다.

그리고 finally 블록의 코드를 실행합니다. finally 블록은 옵션으로 생략이 가능합니다.

 

다중 catch

try 블록 내부는 다양한 종류의 예외가 발생할 수 있는데 이경우 발생되는 예외 별로 예외 처리 코드를 다르게 하려면

다중 catch 블록을 작성하는 것이 좋다.

 

try{

	ArrayIndexOutOfBoundsException 발생
    
    NumberFormatException 발생
    }
    catch(ArrayIndexOutOfBoundsException e) {
    	예외 처리 1
        }catch(NumberForMatException e) {
        예외 처리 2
        }

하지만 catch 블록이 여러 개라도 catch 블록 하나만 실행된다. 그 이유는 try 블록에서 동시 다발적으로 예외가 발생하지 않고 하나의 예외가 발생하면 즉시 실행을 멈추고 행당 catch 블록으로 이동하기 때문입니다.

ex)

package ClassCastException;

public class CatchByExceptionKindExample {
	public static void main(String[] args) {
		
		try {
			//배열생성
			String data1 = args[0];
			String data2 = args[1];
			int value1 = Integer.parseInt(data1);
			int value2 = Integer.parseInt(data2);
			int result = value1 + value2;
			System.out.println(data1 + "+" + data2 +"=" + result);
		} catch(ArrayIndexOutOfBoundsException e) {
			// 배열에 값을 주지않아 
			// System.out.println("실행 매개값의 수가 부족합니다."); 실행될것임
			System.out.println("실행 매개값의 수가 부족합니다.");
		}catch(Exception e) {
			System.out.println("실행에 문제가 있습니다.");
		}finally {
			System.out.println("다시 실행하세요.");
		}
	}
}

 값을 넣어주지 않아 ArrayIndexOutOfBoundsException 이 발생하고

catch(ArrayIndexOutOfBoundsException e)으로 실행에 매개 값의 수가 부족하다고 알려준다.

그 밖의 다른 예외가 발생하면 catch(Exception e) 블록이 실행될 것이다.

 

Multi Catch 기능도 있는데.

한 블록 안에 예외 처리하고 싶은 예외를 | 로 연결해주면 된다.

package ClassCastException;

public class MultiCatchExample {
	public static void main(String[] args) {

		try {
			// 배열생성
			String data1 = args[0];
			String data2 = args[1];
			int value1 = Integer.parseInt(data1);
			int value2 = Integer.parseInt(data2);
			int result = value1 + value2;
			System.out.println(data1 + "+" + data2 + "=" + result);
		} catch (ArrayIndexOutOfBoundsException | NumberFormatException e) {
			// 배열에 값을 주지않아
			// System.out.println("실행 매개값의 수가 부족합니다."); 실행될것임
			System.out.println("실행 매개값의 수가 부족하거나 숫자로 변환할 수 없습니다.");
		} catch (Exception e) {
			System.out.println("알수없는 예외 발생");
		} finally {
			System.out.println("다시 실행하세요.");
		}
	}
}

위의 코드를 조금 변경해보고 실행해보았습니다.

 

'JAVA' 카테고리의 다른 글

컬렉션 프레임워크 Vector  (0) 2022.05.30
컬렉션 프레임워크 ArrayList  (0) 2022.05.30
인터페이스 (default method)  (0) 2022.05.25
2022년 5월 25일 수업중 과제 : 계산기 프로그램  (0) 2022.05.25
인터페이스  (0) 2022.05.24