8장 - 예외처리

JAEUK KIM·2023년 1월 12일
0

자바의 정석

목록 보기
1/3

1.1 프로그램 오류

  • 컴파일 에러: 컴파일 시 발생

  • 런타임 에러: 실행도중 발생

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

    ->예외(exception): 프로그램 코드에 의해서 수습 가능한 미약한 오류
    Exception클래스와 그 자손들: 사용자의 실수와 같이 외적인 요소에 의해 발생(checked예외-예외처리 필수!)
    RuntimeException클래스와 그 자손들: 프로그래머의 실수로 발생(unchecked예외 예외처리 선택!)

  • 논리적 에러: 실행은 되지만, 의도와 다르게 동작

1.2 예외처리하기 try-catch문

예외처리 : 프로그램 실행시 발생할 수 있는 예외에 대비하기 위한 코드 작성(try-catch문 이용) 프로그램의 비정상적인 종료를 막고 정상적인 실행상태를 유지하는 것

But 발생한 예외를 처리하지 못했을 시 프로그램은 비정상 종료되며 JVM의 예외처리기가 처리하지 못한 예외를 받아서 예외의 원인을 화면에 출력

try{
	try{ }	catch(Exception e){ } //try 또는 catch 블럭에 try-catch포함 가능
   
   }catch(Exception **e**){ //변수 e 중복선언. 에러 참조변수 영역이 겹치기 때문에
   		try{ } catch(Exception **e**){ }
        //catch 블럭 괄호에 선언된 변수는 캐치블럭 내에서만 사용가능
       
   } catch(Exception e2){
   		//예외처리
        }

printStackTrace() 예외발생 당시 호출스택(Call Stack)에 있었던 메서드의 정보와 예외 메시지를 화면에 출력
getMessage() 발생한 예외클래스의 인스턴스에 저장된 메시지를 얻는다.

class Exception {
	public void static main(String args[]){
    	System.out.println(1);
        System.out.println(2);
		try{
        	System.out.println(3);
            System.out.println(0/0); //예외발생 catch문으로 넘어감
            System.out.println(4); //실행x
          } catch(ArithmeticException ae){
          		ae.printStackTrace();
                System.out.println("예외메시지 : " + ae.getmessage());
          }  
          System.out.println(9);
        }
      }  

실행결과
1
2
3
java.lang.ArithmeticExeption: /by zero //예외발생 원인
at Exception.main(Exception.java:7) //예외발생 위치
예외메시지: /by zero
9


멀티 catch블럭-코드 중복을 제거하기 위해 ' | '기호를 사용하여 catch 블럭을 하나로 합칠 수 있다. (자주 쓰이지는 않는다.)

try {
	//내용입력
    }catch(ParentException|ChildException e){ //예외클래스가 조상, 자손 관계에 있으면 컴파일에러 조상클래스 하나만 써줘도 되기때문
    	e.printStackTrace();
        }


try {
     //내용입력
    } catch(ExceptionA|ExceptionB e) {
    	e.methodA(); //에러. catch블럭을 합쳤을때는 어떤 예외클래스의 인스턴스가 객체로 연결되었는지 알 수 없음 So ExceptionA ,B의 공통 멤버만 사용 가능
        //여기서 선언된 참조변수e는 여러 catch블럭이 공유하는 상수이므로 값을 변경하는 것은 불가 
        

1.3 예외 발생시키고 직접처리 or 선언하기(떠넘기기)

키워드 throw를 사용해 예외를 발생시킬 수 있다.

  1. 연산자 new 를 사용해 예외클래스의 객체를 생성
              Exception e = new Exception("고의로 발생시켰음");
  2. 키워드 throw를 활용해 예외발생
              throw e;

메서드 선언부에 thrwos키워드를 사용하여 예외를 선언해줄 수 있다.

  • 메서드 내에서 발생할 가능성이 있는 예외를 명시해주어 메서드를 사용하는 쪽에서 어떤 예외를 처리해야 하는지 쉽게 알 수 있다.
import java.io.*;

class Exception{
	public static void main(String args[]){
    try{
    	File f = createFile(args[0]); //args[0]-커멘드 라인을 통해서 입력받음 직접 입력도 가능=createFile(test.txt) 
        System.out.println(f.getName()+"파일이 성공적으로 생성되었습니다.");
        } catch (Exception e) { //createFile메서드로부터 예외를 받아서 처리
        System.out.println(e.getMessage()+"다시 입력해주시기 바랍니다.");
        }
	}
    
   static File createFile(String fileName) throws Exception{//예외 선언후 try-cath문이 있는 main메서드로 예외 던짐
   		if(fileName==null || fileName.equals(""))
        	throw new Exception("파일이름이 유효하지 않습니다."); //객체를 만들고 예외 발생시킴
        File f = new File(fileName);
        f.creatNewfile();
        return f;
      	}
    }  

실행결과
c:\jdk1.9\work\ch8>java Exception test.txt 
test.txt 파일이 성공적으로 생성되었습니다.

c:\jdk1.9\work\ch8>java Exception "" 
파일이름이 유효하지 않습니다. 다시 입력해주시기 바랍니다.

try-catch문은 예외가 발생한 메서드 자체에서 직접 처리하든지 호출한 메서드에서 처리하든지 둘중 하나엔 존재해야함

사용자 정의 예외 만들기
1.Exception클래스 혹은 RuntimeException클래스 중 어떤걸 조상으로 선택할건지 결정 (Exception은 예외처리가 필수이기 때문에 가능하면 RuntimeException 사용하기)

class MyException extends Exception{
	MyException(String msg){//대부분 String 매개변수가 있는 생성자를 만들어준다.
    		super(msg); //조상클래스 생성자의 msg호출

1.4예외 되던지기 및 연결된 예외

class Exception{
	public static void main(String args[]){
    try{
    	method1();
       } catch(Exception e) {
       		System.out.println("main메서드에서 예외가 처리되었습니다."); 
            }//받은 예외를 처리함
    } 
    
    static void method1() throws Exception{
    	try{
        	throw new Exception();
            } catch(Exception e) {
            System.out.println("method1메서드에서 예외가 처리되었습니다.");  //예외처리함
            throw e; //예외를 다시 발생시킴
            }
    	}        
    }        

특별히 어디에 쓰인다는 케이스는 없지만 예외를 분담해서 처리해야 할 때 이렇게 처리할 수도 있다.

1.5 연결된 예외

한 예외를 다른 예외에 포함시켜 연결해줌
Why?
1.예외가 많아지면 그만큼 catch블록이 많아지기 때문에 묶어서 다루면 코드의 길이를 줄일 수 있다.

void install throws InstallException //세부적인 예외처리는 InstallException으로 감싸서 코드의 길이를 효율적으로 줄임
	try{
    	startInstall();
        copyFiles();
      } catch(SpaceException e){//예외A
      		InstallException ie = new InstallException("설치중 예외발생"); //예외B 생성
            ie.initCause(e);//InstallException(예외B)의 원인 예외를 SpaceException(예외A)으로 지정
            throw ie; //예외A를 처리했지만 예외B를 던짐
 Throwable initcause(Throwable cause) 지정한 예외를 원인 예외로 등록하는 생성자
 Throwable getcause() 원인 예외를 반환
  1. checked예외를 unchecked예외로 바꿔 예외 필수처리를 선택처리로 하게 함으로써 의미없는 try-catch 안써도 됌
satic void startInstall() throws SpaceExcepion, MemoryExcepion{
 if(!enoughSpace())
	throw new SpaceException("설치할 공간이 부족합니다.");
 
 if(!enoughMemory())
 	throw new MemoryException("메모리가 부족합니다.");
 }
                       ↓↓↓↓ 

satic void startInstall() throws SpaceExcepion{//Memory를 선택처리로 바꾸었기 때문에 안써줘도 됌   
	if(!enoughSpace())
		throw new SpaceException("설치할 공간이 부족합니다.");
 	
    if(!enoughMemory())
 		throw new RuntimeException(new MemoryException("메모리가 부족합니다."));
 }// RuntimeException(Thrwoable cause)원인 예외를 등록하는 생성자
 
 
 

출처: 자바의 정석3rd Edition 8장 예외처리

profile
Think less, Do it now

0개의 댓글