java

java Exception13

#풀닢 2023. 1. 9. 11:59

Exception

  • 오류와 에러

시스템 상에서 프로그램에 심각한 문제가 발행해서 실행중인 프로그램이 영향을 받는 것은 오류와 예외로 구분할 수 있음

오류(Error) 시스템 상에서 프로그램에 심각한 문제를 발생하여 실행중인 프로그램이 종료되는 것
예외(Exception) 오류와 마찬가지로 비정상적으로 종료시키지만 미리 예측하고 처리할 수 있는 미약한 오류

예외 클래스 계층 구조

Throwable클래스 Exception과 Error 클래스 모두 Throwable클래스의 자손이다.
예외 클래스들의 최상위 클래스는 Exception 클래스이며 예외처리를 해야하는 Checked Exception과 해주지 않아도 되는 Unchecked Exception으로 나뉜다

 

 throws로 위임 (Exception 처리를 호출한 메소드에게 위임) 메소드 선언 시
throws ExceptionName문을 추가하여 호출한 상위 메소드에게 처리를 위임
try-catch로 처리
(Exception이 발생한 곳에서 직접 처리)
 - try : exception 발생할 가능성이 있는 코드를 안에 기술
- catch : try 구문에서 exception 발생 시 해당하는 exception에 대한 처리 기술
여러 개의 exception처리가 가능하나 exception간의 상속 관계 고려
- finally : exception 발생 여부와 관계없이 꼭 처리해야 하는 로직 기술
중간에 return문을 만나도 finally구문은 실행되지만
System.exit();를 만나면 무조건 프로그램 종료
주로 java.io나 java.sql 패키지의 메소드 처리 시 이용

예외 처리 방법

finally로 예외 처리

예외 처리 구문과 상관 없이 반드시 수행해야 하는 경우 작성 (보통 사용한 자원을 반납할 목적)

public static void main(String[] args) {
	ThrowsTest tTest = new ThrowsTest();
	try {
	tTest.methodA();
	} catch (IOException e) {
	e.printStackTrace();
	} finally {
	System.out.println("프로그램 종료");
	}
}

try~with~resource로 예외 처리

자바7에서 추가된 기능으로 finally에서 작성했던 close처리를 try문에서 자동으로 close처리

try (BufferedReader br = new BufferedReader(new FileReader("C:/data/text.txt"))){
	String s;
	while((s = br.readLine()) != null) {
		System.out.println(s);
	}
} catch(FileNotFoundException e) {
		System.out.println("파일이 없습니다.");
} catch(IOException e) {
		e.printStackTrace();
} catch(Exception e) {
		e.printStackTrace();
}

Exception과 오버라이딩

오버라이딩 시 throws하는 Exception의 개수와 상관없이 같거나 후손 범위여야 함

public class Parent {
	public void method() throws IOException{
	. . .
	}
}
public class Child1 extends Parent{
		@Override
		public void method() throws EOFException {
				. . .
	}
}

윗 처럼 코드를 써 주어야 한다.

오류접기

더보기

public class Child2 extends Parent{

                  @Override

                   public void method() throws Exception {

                                        . . .

                        }

}

 


public class Application1 {

	public static void main(String[] args) throws Exception {

Throws로 예외 던지기

메인 메서드 뒤에 throws 라고 적어야 한다.

예외를 발생시키는 메소드를 하나 작성한다.

예외를 발생시키는 메소드를 하나 작성한다.
	public void checkEnoughMoney(int price, int money) throws Exception {	
		System.out.println("가지고 계신 돈은 " + money + "원 입니다.");

		if(money >= price) {
			System.out.println("상품을 구입하기 위한 금액이 충분합니다.");
		} else {
			throw new Exception();
		}
		
		/* 예외가 발생하지 않은 경우에만 실행한다. */
		System.out.println("즐거운 쇼핑하세요.");
	}

강제로 예외를 발생시켜서 예외를 발생 시킨 뒤 메소드 헤드에 throws 구문을 추가한다.

예외를 발생 시킨 쪽에서는 throws로 예외에 대한 책임을 위임해서 해당 예외에 대한 처리를 강제화 시킨다.

			throw new Exception();

 

예외를 발생 시킨 쪽에서는 throws로 예외에 대한 책임을 위임해서 해당 예외에 대한 처리를 강제화 시킨다.


UserException

throws Exception
3개의 예외 클래스는 모두 Exception 클래스의 후손이므로 Exception만으로도 작성할 수 있다 (다형성)
위 section01에서는 Exception을 발생시켰지만 그냥 예외라는 의미가 되므로
예외 클래스의 이름만으로 어떤 예외가 발생했는지 알 수 있도록 사용자 정의 예외를 사용한다.
Exception 사전에 정의 되어 있는 Exception의 종류는 굉장히 많이 있다.
하지만 RuntimeException의 후손 대부분은 예외 처리를 강제화 하지 않는다.
간단한 조건문 등으로 처리가 가능하기 때문에 따로 강제화 하지 않았다.

Exception 클래스 내부에는 별도의 기능은 없고 생성자만 존재한다. 
기본적인 기능은 부모인 Throwable 쪽에 정의 되어 있다.
사전에 정의 된 예외 클래스 외에 개발자가 원하는 명칭의 예외 클래스를 작성하는 것이 가능하다.
extends Exception 예외 처리 클래스를 상속 받아 더 구체적인 예외 이름을 정의하는 것이다.
public class ExceptionTest {
	
	public void checkEnoughMoney(int price, int money) throws PriceNegativeException,
    MoneyNegativeException, NotEnoughMoneyException {		상품 가격이 음수인지 확인하고 음수인 경우 예외 발생
		if(price < 0) {
			throw new PriceNegativeException("상품 가격은 음수일 수 없습니다.");
		}
		
		가진 돈도 음수인지 확인하고 음수인 경우 예외 발생 
		if(money < 0) {
			throw new MoneyNegativeException("가지고 있는 돈은 음수일 수 없습니다.");
		}
		
		위의 두 값이 정상 입력 되었더라도 상품 가격이 가진 돈 보다 큰 경우 예외 발생 
		if(money < price) {
			throw new NotEnoughMoneyException("가진 돈 보다 상품 가격이 더 비쌉니다.");
		}
		
		모든 조건을 만족하는 경우 정상적으로 물건 구입 가능
		System.out.println("가진 돈이 충분합니다. 즐거운 쇼핑 하세요~");

이렇게 하나의 클래스 만들고 아래 동작할 수 있는 어플리케이션 다시 만든다.

  • 각각의 예외 상황에 다른 조치가 필요할 경우 예외마다 catch 블럭을 나눠서 작성 가능.
		ExceptionTest et = new ExceptionTest();
		
		try {
			et.checkEnoughMoney(50000, 30000);
		} catch (PriceNegativeException e) {
			e.printStackTrace();
		} catch (MoneyNegativeException e) {
			e.printStackTrace();
		} catch (NotEnoughMoneyException e) {
			e.printStackTrace();
		}
  • 모든 예외 상황에 같은 조치를 할 경우 catch 블럭을 multi-catch 블럭으로 작성할 수 있다.
		try {
			/* 상품 가격보다 가진 돈이 작은 경우 */
			//et.checkEnoughMoney(50000, 30000);
			/* 상품 가격을 음수로 입력한 경우 */
//			et.checkEnoughMoney(-50000, 30000);	
			/* 가진 돈을 음수로 입력한 경우 */
//			et.checkEnoughMoney(50000, -30000);
			/* 정상 동작 */
			et.checkEnoughMoney(30000, 50000);
			
	} catch (PriceNegativeException | MoneyNegativeException | NotEnoughMoneyException e) {			
		e.printStackTrace();	//콘솔창에 예외 출력 메소드
	}
    		/* 예외가 발생하더라도 catch 블럭 실행 후 정상 흐름으로 돌아온다. */
		System.out.println("프로그램을 종료합니다.");
더보기

가진 돈이 충분합니다. 즐거운 쇼핑 하세요~

프로그램을 종료합니다.

userexception.exception 아래 메세지 뜨게 만들어 놓기

	public MoneyNegativeException() {}
	
	public MoneyNegativeException(String message) {
		super(message);
	}
    
    	public NotEnoughMoneyException() {}
	
	public NotEnoughMoneyException(String message) {
		super(message);
	}
	
}

	public PriceNegativeException() {}
	
	public PriceNegativeException(String message) {
		super(message);
	}

}

Uses-IO

예외 처리를 가장 많이 활용해야 하는 것이 IO(input/output) 패키지이다. 

아직 IO를 배우지 않았지만 IO 문법보다 try-catch 블럭의 실제 사용과 흐름에 집중해서 살펴보자. 

finally 블럭에서 사용하려면 레퍼런스 변수를 try 블럭 밖에서 선언해야 한다.

input  
output  

finally 블럭에서 사용하려면 레퍼런스 변수를 try 블럭 밖에서 선언해야 한다.

		BufferedReader in = null;

 FileReader라는 클래스의 생성자에 예외를 throws 해 놓았다.
 사용하는 쪽에서 반드시 예외처리를 해야하기 때문에 try-catch 블럭 안에서 생성자를 호출하여 인스턴스를 생성해야 한다.

try {
	FileReader라는 클래스의 생성자에 예외를 throws 해 놓았다.
	사용하는 쪽에서 반드시 예외처리를 해야하기 때문에 try-catch 블럭 안에서
	생성자를 호출하여 인스턴스를 생성해야 한다.
		in = new BufferedReader(new FileReader("test.dat"));
	
		String s;
			
	readLine() 메소드도 IOException을 throws 하므로 catch 블럭을 추가해서 예외 처리 구문을 작성해야 한다.
		while((s = in.readLine()) != null) {
			System.out.println(s);
		}
			
			
	} catch (FileNotFoundException | EOFException e) {	//FileNotFoundException : 해당 파일을 찾지 못한 예외
	FileNotFoundException과 EOFException을 동시에 처리할 수 있다. (multi-catch) 
	같은 레벨의 자손을 한 번에 처리할 수 있다.
		e.printStackTrace();
	} catch (IOException e) {
	IOException 입출력에 관해 추상화 된 예외로 FileNotFoundException은 IOException의 후손이다.
	catch 블럭은 여러 개를 작성할 시 상위 타입이 하단에 오고 후손 타입이 먼저 작성되어야 한다.
	상위 타입이 위에 오면 다형성 적용에 의해 아래 catch 블럭까지 도달하지 못한다.
		e.printStackTrace();
	} finally {
			
	예외 처리 구문과 상관 없이 반드시 수행해야 하는 경우 작성하며 보통 사용한 자원을 반납할 목적으로 사용하게 된다. */
		try {
	입출력에 사용한 스트림을 닫아주는 메소드이다.
	IOException을 위임한 메소드이기 때문에 finally 블럭 안이더라도 예외처리를 중첩으로 해주어야 한다. */
				
	NullPointerException은 unchecked exception이므로 보통 if 구문으로 해결 가능하다. */
		if(in != null) 
			in.close();	
				
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}

try-with-resource

try-with-resource
JDK 1.7에서 추가 된 문법으로 close 해야하는 인스턴스의 경우
try 옆에 괄호 안에서 생성하면

해당 try-catch 블럭이 완료 될 때 자동으로 close 처리 해준다. 
try (BufferedReader in = new BufferedReader(new FileReader("test.dat"))) {
	} catch (FileNotFoundException e) {
		e.printStackTrace();
	} catch (IOException e) {
		e.printStackTrace();
	}
	}

SuperClass
예외를 던지는 메소드를 하나 작성한다. 
public void method() throws IOException {}
SubClass 1.같은 예외를 던져주는 구문으로 오버라이딩 할 수 있다
@Override
public void method() throws IOException {}

2.부모의 예외처리 클래스보다 상위의 예외로는 후손 클래스에서 오버라이딩 할 수 없다.
@Override
public void method() throws Exception {}

3.부모의 예외처리 클래스보다 더 하위에 있는 예외(즉, 더 구체적인 예외)인 경우에는 오버라이딩 할 수 있다.
@Override
public void method() throws FileNotFoundException {}

4.예외 없이 오버라이딩 할 수 있다.
@Override
public void method()  {}

 


RuntimeException 후손 클래스

ArithmeticException 0으로 나누는 경우 발생 if문으로 나누는 수가 0인지 검사
ArrayIndexOutOfBoundsException 배열의 index범위를 넘어서 참조하는 경우 배열명.lengt를 사용하여 배열의 범위 확인
NullPointerException Null인 참조 변수로 객체 멤버 시도 시 발생 객체 사용 전에 참조 변수가 null인지 확인
- ClassCastException Cast연산자 사용 시 타입 오류 instanceof연산자로 객체 타입 확인 후 cast연산
NegativeArraySizeException 배열 크기를 음수로 지정한 겨우 발생 배열 크기를 0보다 크게 지정

 

SMALL