본문 바로가기

코딩/JAVA 공부

[JAVA] 자바의 정석 _ 예외 (try-catch 문)

 * 프로그램 오류

1. 컴파일 에러 : 컴파일할 때 발생하는 에러

컴파일러가 하는 일 : 구문 체크, 번역, 최적화, 생략된 코드 추가

 

2. 런타임 에러 : 실행 중 발생하는 에러

- 에러(error) : 프로그램 코드에 의해서 수습될 수 없는 심각한 오류

- 예외(exception) : 프로그램 코드에 의해서 수습될 수 있는 다소 미약한 오류

에러는 어쩔 수 없지만, 예외는 처리할 수 있음!

 

** 프로그램 작성시 런타임 에러보단 컴파일 에러가 더 좋다.

컴파일 에러는 프로그램 실행 전 파악 가능해 바로 고칠 수 있지만, 런타임 에러는 실행하던 도중 꺼져버려서 그 전에 입력값 등이 모두 사라져버림..

 

예외(exception)의 종류

     - Exception 클래스 : 사용자의 실수와 같은 외적인 요인에 의해 발생하는 예외

         ex) 입출력 예외, 클래스 파일 부재

     - RuntimeException 클래스 : 프로그래머의 실수로 발생하는 예외

         ex) 배열 범위 벗어남, 산술 계산 예외, 널포인터, 형 변환 오류

 

3. 논리적 에러 : 작성 의도와 다르게 동작

 

 * 예외처리 (try-catch 문) (직접 처리하기)

정의: 프로그램 실행 시 발생할 수 있는 예외 발생 대비한 코드를 작성하는 것

목적: 프로그램의 비정상 종료를 막음

try{
		// 예외 발생 가능성 있는 문장 넣기
} catch (Exception1 e1) {
		// Exception1 이 발생한 경우, 이를 처리할 문장 넣기
}

try 블럭 내에서 예외가 발생한 경우,

발생한 예외와 일치하는 catch 블럭 수행 후, 전체 try-catch 블럭을 빠져나가서 그다음 문장 수행.

Exception이 선언된 catch블럭은 모든 예외 처리. 마지막 catch 블럭

class EX8{
    public static void main(String args[]){
    	System.out.println(1);
        try{
        	System.out.println(0/0); // 예외 발생!
            System.out.println(2);
            
        } catch (ArithmeticException ae){
        	System.out.println(3);
            
        } catch (Exception c){
        	System.out.println(5);
        }
        System.out.println(4);
    } //main end
}//class end
//출력 : 1 3 4 (2는 건너뛰고 수행 안함, 5는 이전 catch 블럭을 통해 이미 빠져나갔으므로 수행 안함)

예외가 발생하면 예외 객체가 생성됨.

   ex) 0/0 의 경우 ArithmeticException 객체 생성.

예외 객체 안에는 printStackTrack(), getMessage() 같은 메서드가 들어있음.

printStackTrack(), 예외발생 당시의 호출스텍(Call Stack)에 있었던 메서드의 정보와 예외 메시지 화면 출력
getMessage() 발생한 예외클래스의 인스턴스에 저장된 메시지를 얻을 수 있음 (String 반환)

 

 * 멀티 catch블럭

내용이 같은 catch블럭을 하나로 합친 것.

try{
} catch (ExceptionA e){
	//내용 1
} catch (ExceptionB e2){
	//내용 1
}
//-----------------------------------------------------------------------------------------

try{
} catch (ExceptionA | ExceptionB e){
	// ExceptionA 와 ExceptonB의 공통멤버만 사용 가능.
	
    if(e instanceof ExceptionA){
    	//내용 형변환 후 내용~~
    } else{
    
    }
}

 

 * 예외 발생시키기

1. 예외 객체를 만든 다음

2. 키워드 throw를 이용해 예외 발생

class Ex8{
    public static void main(String at\rgs[]){
    try{
    	Exception e = new Exception("고의로 발생시켰음.");
        throw e;
    } catch (Exception e){
    	System.out.println("에러 메시지 : " + e.getMessage());
        e.printStackTrack();
    }
    System.out.println("프로그램이 정상 종료되었음.");
    }// main end
} // class end

 

* checked예외, unchedked예외

checked 예외
(Exception 클래스)
컴파일러가 예외 처리 여부를 체크 (예외 처리 필수)
unchecked 예외
(RuntimeException 클래스)
컴파일러가 예외 처리 여부 체크 안함 (예외 처리 선택)

checked 예외는 예외 처리 안 한 경우 컴파일에서 체크해 run 자체를 못함. (try-check 필수)

unchecked예외는 예외 처리 안 해도 컴파일 후 run은 가능, 이후 예외 발생. (try-check 선택)

 : 만약 이게 필수였다면 거의 모든 코드에 try-catch 구문을 넣어야 함..

 

 * 예외처리 (예외 선언하기) (예외 떠넘기기)

- 메서드가 호출 시 발생 가능한 예외를 호출하는 쪽에 알리는 것 (폭탄 돌리기라고 생각하면 편함!)

void startInstall() throws SpaceException, MemoryException {
    if(!enoughSpace())
    	throw new SpaceException("설치 공간이 부족합니다.");
    if(!enouthMemory())
    	throw new MemoryException("메모리가 부족합니다.");
}

startInstall 메서드를 사용하는 쪽 에서는 throws에 적힌 예외 문에 대한 try-catch문이 있어야 함.

import java.io.File;

public class EX7_2 {
	public static void main(String[] args) {
		try {
			File f = createFile("");
			System.out.println(f.getName() +"파일이 성공적으로 생성되었습니다. ");
		} catch (Exception e) {
			
			System.out.println(e.getMessage() + "다시 입력해 주시기 바랍니다.");
		}
	}// main end

	static File createFile(String fileName) throws Exception{
		if(fileName == null || fileName.equals(""))
			throw new Exception("파일 이름이 유효하지 않습니다.");
		File f = new File(fileName);
		f.createNewFile();
		return f;
	}// createFile end
}// EX7_2 end

throws 하지 않고, 발생한 곳에서 바로 처리하기

import java.io.*;

public class EX7_2 {
	public static void main(String[] args) {
			File f = createFile("");
			System.out.println(f.getName() +"파일이 성공적으로 생성되었습니다. ");
	}// main end

	static File createFile(String fileName){
		try {
			if(fileName == null || fileName.equals(""))
				throw new Exception("파일 이름이 유효하지 않습니다.");			
		} catch(Exception e) {
			fileName = "제목없음.txt";
		}
		
		File f = new File(fileName);
		try {
			f.createNewFile();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return f;
	}// createFile end
}// EX7_2 end

 * finally블럭

- 예외 발생 여부와 관계없이 수행되어야 하는 코드

try-catch 블럭 제일 끝에 위치

try{
    //예외 발생 가능한 문장
} catch (Eaception1 e1){
    //예외 발생시 처리할 문장
} finally{
    // 예외 발생 유무와 상관없이 수행할 문장
}

 

 * 예외 되던지기

예외를 처리하고 그걸 다시 throws로 던짐. 양쪽에서 처리

 

 * 연결된 예외(chained exception)

발생한 예외(A)를 try-catch 문으로 잡은 다음에 그것과 연관된 다른 예외(B)를 발생시킴.

이때 B의 원인에 A를 등록

Throwable initCause (Throwable cause) : 지정한 예외를 원인 예외로 등록

Throwable hetCause()  : 원인 예외를 반환

void install() throws InstallException{
    try{
    	startInstall(); // 수행 도중 SpaceException 에러 발생
        coptFiles();
    } catch (SpaceException e){
    	InstallException ie = new InstallException("설치중 예외 발생");
        ie.initCause(e); // InstallException의 원인 예외를 SpaceException으로 지정
        throw ie;
    } catch (MenoryException me) {....