10.예외와 예외 클래스

chaean Lee·2021년 2월 10일
0
post-thumbnail

이 글은 제가 공부한 것들을 정리한 것입니다.

10.1 예외와 예외클래스

에러: 하드웨어 오작동

예외: 사용자의 잘못된 조작, 개발자의 잘못된 코딩.

예외 종류

-일반예외(Exception),실행예외(RuntimeExceiption)

✔일반예외

  • 컴파일 하는 과정에서 예외처리코드가 필요한지 검사한다.
  • 만약 예외처리가 필요한 코드에 예외 처리 코드가 없다면 컴파일 오류가 발생한다. * 일반예외는 Exception을 상속받지만 RuntimeException을 상속받지 않는다.

✔실행예외

  • 컴파일시 예외 처리를 확인하지 않는다.
  • RuntimeException을 상속받는 클래스들이다. RuntimeException 역시 Exception을 상속받지만 JVM은 RuntimeException을 상속했는지 여부를 보고 실행예외를 판단한다.

10.2 실행예외

10.2.1 NullPointerException

10.2.2 ArrayIndexOutOfBoundException

10.2.3 NuberFormatException

10.2.4 ClassCastException

10.3 예외처리 코드

✨일반 예외처리
public class TryCatchFinallyExample {
	
	public static void main(String[] args) {
		
		try {
			Class Class = Class.forName("java.lang.String2");
		} catch (ClassNotFoundException e) {
			System.out.println("클래스가 존재하지 않습니다.");
			e.printStackTrace();
		}
	}

}



✨실행예외처리 - 오로지 개발자의 경험에 의해 작성해주어야 한다.
public class TryCatchFinallyRuntimeExceptionExample {

	public static void main(String[] args) {
		String data1 = null;
		String data2 = null;

		try {
			data1 = args[0];
			data2 = args[1];
		} catch (ArrayIndexOutOfBoundsException e) {
			System.out.println("실행 매개값의 수가 부족하다.");
			System.out.println("[실행 방법]");
			return;

		}

		try {
			int value1 = Integer.parseInt(data1);
			int value2 = Integer.parseInt(data2);
			int result = value1 + value2;

		} catch (NumberFormatException e) {
             System.out.println("숫자로 변환 할 수 없습니다.");
		} finally {
			System.out.println("다시 실행 하세요.");
		}
	}

}

10.4 예외종류에 따른 처리 코드

10.4.1 다중 catch

public class CatchByExeptionKindExample {
	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 (NumberFormatException e) {
			System.out.println("숫자로 변환 할 수 없습니다.");
		} finally {
			System.out.println("다시 실행 하세요.");
		}
	}

}

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

10.4.2 catch 순서

다중 catch블록 작성시 주의할 점은 상위 예외 클래스가 하위 예외 클래스보다 아래에 위치해야 한다. 하위 예외는 상위 예외를 상속했기 때문에 상위 예외 타입도 되기 때문이다.

10.4.3 멀티 catch

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("실행 매개값의 수가 부족하거나 숫자로 변환할 수 없습니다.");

		} catch (Exception e) {
			System.out.println("알수 없는 예외.");
		} finally {
			System.out.println("다시 실행 하세요.");
		}
	}

}

10.5 자동 리소스 닫기

자바 7에서 새로 추가된 try-with-resources 를 사용하면 예외 발생 여부와 상관없이 사용했던 리소스 객체(각종 입출력 스트림, 서버 소켓, 소켓 , 각종 채널)의 close()메소드를 호출해서 안전하게 리소스를 닫아준다.

리소스는 간단히 데이터를 읽고 쓰는 객체라고 생각하자.

FileInputStream fis = null;
		try {
			fis = new FileInputStream("file.txt");
		} catch (FileNotFoundException e) {

		} finally {
			
			if (fis != null) {
				try {
					fis.close();
				} catch (IOException e) {

				}
			}
		}
        
//✨자바 7에서 새로 추가됬다.

try (FileInputStream fis = new FileInputStream("file.txt")) {

		} catch (IOException e) {

		}
//✨try 블록이 정상적으로 실행을 완료했거나 예외가 발생하게 되면 자동으로 
  FileInputStream의 close() 메소드가 호출된다.
  
//✨복수개의 리소스를 작성할 수 도 있다.

try (FileInputStream fis1 = new FileInputStream("file.txt");
	   FileInputStream fis2 = new FileInputStream("file.txt")) {

		} catch (IOException e) {

		}
        
//✨try - with - resources를 사용하기 위해서는 조건이 있는데
리소스 객체는 java.lang.AutoCloseable 인터페이스를 구현하고 있어야 한다.


public class FileInputStream implements AutoCloseable {

	private String file;

	public FileInputStream(String file) {
		this.file = file;
	}

	public void read() {
		System.out.println(file + "를 읽습니다.");
	}

	@Override
	public void close() throws Exception {
		System.out.println(file + "를 닫습니다.");

	}
}




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

		try (FileInputStream fis = new FileInputStream("file.txt")) {
			fis.read();
			throw new Exception();// 강제로 예외 발생
		} catch (Exception e) {
			System.out.println("예외처리 코드가 실행되었습니다.");
		}
	}

}

10.6 예외 떠넘기기

메소드 내부에서 예외가 발생할 수 있는 코드를 try-catch 구문으로 예외를 처리하는 것이 기본이지만, 메소드를 호출한 곳으로 예외를 떠넘길 수 도 있다. 이때 사용하는 키워드가 throws이다.

public void method1() {
	try {
			method2();
		} catch (ClassNotFoundException e) {
			System.out.println("클래스가 존재하지 않습니다.");
			}
}
		
		
 public void method2() throws ClassNotFoundException{
	Class class = Class.forName("java.lang.String2");
		}

10.7 사용자 정의 예외와 예외 발생

자바에서 제공하는 클래스만으로 다양한 예외를 표현할 수가 없다. 예를 들어 은행업무를 처리하는 프로그램에서 잔고보다 더 많은 출금 요청이 들어왔을 경우 오류가 되며 잔고 부족 오료를 발생시킬 필요가 있는데, 잔고부족 API는 자바에 존재하지 않는다. 이럴 경우 개발자가 직접 정의해서 만들어야 하므로 사용자 정의 예외라고 한다.

10.7.1 사용자 정의 예외 클래스 선언

public class BalanceInsufficientException extends Exception {
            //사용자 정의 예외 클래스 이름은 Exception으로 끝나는 것이 좋다.
            //사용자 정의 예외 클래스도 필드, 생성자, 메소드 선언들을 포함할 수 있지만,
            //대부분 생성자 선언만을 포함한다.
            //생성자는 두개가 일반적인데,하나는 기본생성자
            //다른 하나는 예외 발생 원인을 전달하기 위해 Stirng 타입의 매개 변수를 갖는 생성자이다.
            //String 타입의 매개변수를 갖는 생성자는 상위 클래스의 생성자를 
            //호출하여 예외 메시지를 넘겨준다.
	public BalanceInsufficientException() {
	}

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

}


public class Account {

	private long balance;

	public Account() {
	}

	public long getBalance() {
		return balance;
	}

	public void deposit(int money) {
		balance += money;
	}

	public void withdraw(int money) throws BalanceInsufficientException {

		if (money > balance) {
			throw new BalanceInsufficientException("잔고 부족: " + (money - balance) + "이 모자람.");
		}
		balance -= money;
	}

}




public class AccountExample {

	public static void main(String[] args) {
		Account acc = new Account();
		acc.deposit(10000);
		System.out.println("예금액:" + acc.getBalance());
		try {
			acc.withdraw(30000);
		} catch (BalanceInsufficientException e) {
			System.out.println("meassage:" + e.getMessage());
			System.out.println();
			e.printStackTrace();
		}
	}
}
profile
왜! 언제! 어떻게! 😁

0개의 댓글