본문 바로가기
Java

[Java] 예외처리

by 콧등치기국수 2021. 5. 25.

1. 에러

1) 컴파일에러 : 코드상의 문법 에러로 인해 프로그램 실행이 안됨

                    에러가 발생한 소스 구문을 수정하여 해결

2) 런타임에러 : 프로그램 실행시 발생하는 에러(입력값 틀렸거나, 배열의 인덱스 범위를 벗어났거나, 계산식의 오류 등)                      주로 if문사용으로 에러 처리(nullpointerException -> 변수 != null)

                    프로그래머의 부주의로 인한 오류인 경우가 많기 때문에 예외 처리보다는 코드를 수정해야 함

3) 시스템에러 : 소스 구문으로 해결 불가(컴퓨터 오작동, 메모리 등)

 

소스수정으로 해결가능한 오류 -> exception

 

 

2. 예외클래스의 상속관계

출처 : http://tcpschool.com/java/java_exception_class

0) 자바에서 사용가능한 예외클래스의 최상위 -> Exception클래스 

- nullpointerexception , IOException 모두 Exception클래스로 받을 수 있다.

 

1) unchecked Exception : 컴파일러가 예외처리 여부 확인안해줌 / 표시는 안해주지만 실행을 시키면 오류로 인해 비정상적으로 프로그램이 종료됨

* 예외처리방법 : if문 / try-catch구문 / thorws

* Runtime Exception과 후손클래스들

- nullpointerexception : 참조변수가 null로 초기화된 상태에서 메소드 호출

- indexoutofBoundsException : 배열에서 인덱스범위에 문제

- ArithmeticException : 0으로 나누기

- ClassCastException : 형변환 문제

- NegativeArraySizeException : 배열크기 음수

 

2) checked Exception : 꼭 실행전에 처리를 해줘야 함 / 빨간 줄로 표시됨

* 주로 외부 매개체의 입출력시 발생 -> IOException(입출력할때 발생) -> 예외처리 해야함

* 예외처리방법 : try-catch구문 / thorws

Exception>IOException > EOFException

 

 

2. 예외처리 방법

예외 : 소스코드 수정으로 해결이 가능한 에러

예외처리 : 예외상황(예측가능한 에러)의 구문을 처리하는 방법

              프로그램이 비정상적으로 종료되지 않도록 처리할 수 있다.

(소스코드 수정으로 해결이 가능하므로 가능하다면 소스코드 수정으로 해결)

 

 

1) throws 사용 : 해당메소드를 호출한 상위 메소드에게 예외 던지기(위임)

메소드 선언시throwsExceptionName문을 추가하여 호출한 상위메소드가 예외처리를 하도록 던지는 방법이다.
계속위임하면 main()메소드까지 위임하게되고 거기서도 처리되지 않는 경우 비정상종료

접근제어자 반환자료형 메소드명([자료형 매개변수]) throws 처리할예외클래스명 {

	// 예외를 처리해야 하는 구문
}

 

 

- 여러 단계로 떠 넘길 수 있다.

public void methodA() throws IOException {
    methodB();
}

public void methodB() throws IOException {
    methodC();
}

public void methodC() throws IOException {

    throw new IOException();  //예외발생
}

 

 

2) try ~ catch구문 사용 : 예외처리 구문을 사용하여 직접 처리

try {
	// 예외발생이 예측되는 구문(반드시 예외를 처리해야 하는 구문 )
}
catch( 처리할예외클래스명 레퍼런스(참조변수)) {
	// 발생 한 예외에 대한 처리 구문 작성
} finally {
	// 예외 발생 하던 안하던 간에 반드시 실행되어야 하는 구문
}

▶ finally : 실행 도중 해당 Exception이 발생하든 안 하든 반드시 실행해야 되는 구문

            필수적으로 적어줘야 하는 것은 아님

            중간에 return;을 만나도 finally문은 실행 O

            System.exit(0); 을 만나면 finally문 실행 X

 

 

Unchecked Exception (Run-time Exception)
System.out.println("정수 1 : ");
int num1 =sc.nextInt();	
System.out.println("정수 2 : ");
int num2 =sc.nextInt();

int result1= 0;
try {
	result1 = num1/num2;
} catch(ArithmeticException e) {
	System.out.println("0으로 나눌 수 없습니다.");
}

1) catch(ArithmeticException e)

--> 변수 e , 변수 e의 데이터 타입은 ArithemethicException

--> catch옆에 처리할 예외클래스명과 레퍼런스변수를 꼭 적어주자

 

try {
		//ClassCastException
		Object obj = 'a'; //char -> (autoBoxing) -> Character -> (다형성) -> Object
		String str = String.valueOf(obj);
			
		//ArrayIndexOutOfBoundsException
		int[] arr = new int[2];
		arr[0] = 1;
		arr[1] = 2;
		//arr[2] = 3;
			
		//NullPointerException
		String str1 = null;
		int length = str1.length();

		/*Multi catch문 --> 나란히 작성하는 경우 형제레벨만 함께 사용*/
		}catch(ClassCastException | ArrayIndexOutOfBoundsException | NullPointerException e) {
			System.out.println("잘못 형변환했네 다형성 복습!!");
            		System.out.println(e);
//			e.printStackTrace();  //가장 보편적으로 쓰임
//			System.out.println(e.getMessage());
//			System.out.println(e.toString());			
//			System.exit(0);  //프로그램 강제 종료(0: 정상적으로 종료) ==> finally도 실행X
//			return;  //상위 메소드로 돌아감 ==> finally는 실행
			
		}finally {
			System.out.println("여전히 실행하네");
		}
		
		System.out.println("출력");  //System.exit(0) / return없을 때

0) catch(ClassCastException | ArrayIndexOutOfBoundsException | NullPointerException e) { }

- multicatch문

- 형제레벨만 나란히 작성가능하다.

 

1) e.printStackTrace();  

- 가장 보편적으로 쓰임

- 리턴값이 없고 printStackTrace를 호출하면 메소드가 내부적으로 예외 결과를 화면에 출력한다. 

- printStackTrace는 가장 자세한 예외 정보를 제공한다.


2) System.out.println(e.getMessage());

- getMessage는 오류의 원인을 간단하게 출력


3)  System.out.println(e.toString());

- 에러의 Exception 내용과 원인을 출력


4) System.exit(0);  //프로그램 강제 종료(0: 정상적으로 종료) ==> finally도 실행X
5) return;  //상위 메소드로 돌아감 ==> finally는 실행

 

 

 

 

 

Checked Exception (IOException)
public void method22() { //throw적어줘야 한다.
	byte[] bArr = {'I', 'O', 'E'};
	System.out.write(bArr);

}

1) bArr라는 배열을 생성하여 각 칸에 'I', 'O', 'E' 를 넣어주고 System.out 안의 write(bArr)메소드를 통해 bArr의 요소들을 모두 출력하는 코드이다.
2) 위의 코드를 그냥 실행한다면 에러가 발생하면서 컴파일이 되지 않는다.


3) 위 API설명에서와 같이 보조스트림인 PrintStream의 write메소드는 기본적인 예외 처리가 되어 있지 않기 때문이다.

4) 따라서 아래와 같이 수정해주면 잘 작동하는 것을 확인할 수 있다.

throws 예외처리 - 호출한 메소드에서 try, catch로 잡아줘야 한다. 끝없이 throw할 수 없다.
try ~ catch 예외처리

 

 

 

 

 

 

 

 

 

 

 

출처 :

kh정보교육원 강의자료

https://wikidocs.net/229

https://butterflp01.tistory.com/89?category=327707