기록

*20일차 (Exception) 본문

학원/강의

*20일차 (Exception)

pringspring 2022. 2. 21. 10:02

@예외처리 (Exception)

 

*정의

  -프로그램 오류중 적절한 코드에 의해서 정상적인 처리흐름으로 수습가능한 미약한 오류.

 

*처리방법

  1. 예외처리 : try ~ catch
  2. 예외던지기 : throws

 

*예외의 종류

  1. Unchecked Exception 예외처리 강제화 X. RuntimeException후손클래스 모두.
  2. Checked Exception 예외처리 강제화. RuntimeException후손 외 모든 클래스

 

 

#try catch

 

 *예외처리

  • try 예외가 발생할 수 있는 구문 작성
  • catch 예외가 발생했을 때 처리할 구문 작성
  • Ex) 
	public void test1() {
		while(true) {
			try {
				String s = null;
				if(new Random().nextBoolean())
					s = "hello";
				System.out.println(s.length());
				
				System.out.print("정수1 입력 : ");
				int a = sc.nextInt();
				System.out.print("정수2 입력 : ");
				int b = sc.nextInt();
				System.out.printf("%d / %d => %d%n", a, b, a / b);
				// java.lang.ArithmeticException: / by zero
				
				break;
			} catch(ArithmeticException e) {
				System.out.println("0으로 나눌수 없습니다.");
			} catch(InputMismatchException e) {
				System.out.println("숫자만 입력하세요.");
				sc.next(); // 입력버퍼 비우기
			} catch(NullPointerException e) {
				System.out.println("NPE가 발생했습니다.");
			}
			System.out.println("반복문 끝!");
		}
	}

 

 

 

 

*흐름

 -finally 블럭 

  • 예외가 발생하든 안하든 무조건 실행되는 블럭
  • try에서 사용한 자원반납하는 코드등을 작성
  • Ex)
	public void test1() {
		while(true) {
			try {
				String s = null;
				if(new Random().nextBoolean())
					s = "hello";
				System.out.println(s.length());
				
				System.out.print("정수1 입력 : ");
				int a = sc.nextInt();
				System.out.print("정수2 입력 : ");
				int b = sc.nextInt();
				System.out.printf("%d / %d => %d%n", a, b, a / b);
				// java.lang.ArithmeticException: / by zero
				
				break;
			} catch(ArithmeticException e) {
				System.out.println("0으로 나눌수 없습니다.");
			} catch(InputMismatchException e) {
				System.out.println("숫자만 입력하세요.");
				sc.next(); // 입력버퍼 비우기
			} catch(NullPointerException e) {
				System.out.println("NPE가 발생했습니다.");
			}
			System.out.println("반복문 끝!");
		}
	}

 

 

*catch절 작성순서

  • 상속관계가 없을때는 순서 상관 없다.
  • 다형성을 적용할 수 있다.
  • 부모/자식클래스 catch블럭을 모두 작성해야 하는 경우, 자식 - 부모순으로 작성해야 한다.
  • Ex) 
private void test3() {
		try {
//			System.out.println("정수입력 : ");
//			int n = sc.nextInt(); 
//			
//			System.out.println(100 / 0); // ArithmeticException
//			
//			String s = null;
//			System.out.println(s.hashCode()); // NullPointerException
			
			int[] arr = new int[3];
			System.out.println(arr[100]); // ArrayIndexOutOfBoundsException
		
//		} catch(NullPointerException e) {
//			System.out.println("NullPointerException!!");
//		} catch(ArrayIndexOutOfBoundsException e) {
//			System.out.println("ArrayIndexOutOfBoundsException!!");
//		} catch(ArithmeticException e) {
//			System.out.println("ArithmeticException!!");
//		} catch(RuntimeException e) {
//			System.out.println("RuntimeException!");
//			System.out.println(e);
		} catch(Exception e) {
			System.out.println("Exception!!");
			System.out.println(e);
		}	
		
	}

*블럭 / 변수 유효범위

	public void test5() {
		int a = 0;
		try {
//			int a = 10;
			a = 10;
		} catch(Exception e) {
			System.out.println(a);
		} finally {			
			System.out.println(a);
		}
		System.out.println(a);
	}

 

 

*Ex)

사용자로부터 정수 2개를 입력받아 합을 출력하세요.
예외가 발생할 수 있는 상황을 고려해 예외처리구문 작성하세요.

	public void test4() {
		int a = 0;
		int b = 0;
		
		while(true) {
			try {
				System.out.print("정수 1 입력 : ");
				a = sc.nextInt();
				System.out.print("정수 2 입력 : ");
				b = sc.nextInt();
				
				break;
			} catch(InputMismatchException e) {
				System.out.println("정수만 입력하실 수 있습니다.");
				sc.next(); // 버퍼비우기용
			}			
		}
		
		System.out.printf("%d + %d = %d%n", a, b, a + b);
		
	}

 

 

 

#커스텀 예외클래스 작성

 

 *정의

   -Unchecked Exception 생성할 경우 RuntimeException 상속

   -Checked Exception 생성할 경우 Exception 상속

public class UnderAgeException extends RuntimeException {

	public UnderAgeException() {
		super();
	}

	public UnderAgeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
		super(message, cause, enableSuppression, writableStackTrace);
	}

	public UnderAgeException(String message, Throwable cause) {
		super(message, cause);
	}

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

	public UnderAgeException(Throwable cause) {
		super(cause);
	}
}

 

 

 

#throw

  • main메소드에서 throws예외구문을 작성하는 것은 예외처리를 안하는 것과 같다.
  • 예외발생시 비정상종료된다. 
public static void main(String[] args)/* throws Exception */{
		ThrowExceptionStudy study = new ThrowExceptionStudy();
//		study.test1();
//		study.test2();
//		study.test3();
		study.test4();
		System.out.println("----- 프로그램 정상 종료 -----");
	}

 

* if ~ else를 통한 분기처리

private void test1() {
		boolean bool = checkAge1();
		if(bool) {
			startGame();			
		}
		else {
			System.out.println("게임을 즐길수 있는 적정연령이 아닙니다. 종료합니다.");
		}
	}
	
	public boolean checkAge1() {
		System.out.print("나이를 입력 : ");
		int age = sc.nextInt();
		if(age >= 20)
			return true;
		else 
			return false;
	}
	
	
	/**
	 * 성인만 즐길수 있는 게임.
	 */
	public void startGame() {
		System.out.println("게임시작...");
	}

 

*exception을 통한 분기처리

private void test2() {
		try {
			checkAge2(); // 사용자 나이검사			
			startGame();
		} catch(Exception e) {
			e.printStackTrace(); // 콘솔에서 확인용(사용자 노출되지 않는다고 가정)
			System.out.println("게임을 즐길수 있는 적정연령이 아닙니다. 종료합니다.");
		}
	}
	
	/**
	 * 나이 검사후 20세미만인 경우 예외를 던지는 메소드
	 * - 현재메소드를 호출한 쪽에 예외를 던지게 된다.
	 * 
	 * 커스텀 예외클래스 작성 가능
	 * - UnderAgeException 현재 오류상황을 잘 설명할 수 있는 예외클래스를 작성할 것!
	 */
	public void checkAge2() {
		System.out.print("나이를 입력 : ");
		int age = sc.nextInt();
		if(age < 20)
			throw new UnderAgeException("미성년자 : " + age); 
	}

 

 

 

#Checked/Unchecked

*Checked Exception - 예외처리를 강제화

*Unchecked Exception - RuntimeException의 후손클래스, 예외처리 강제화하지 않는다.

	private void test3() {
		// 해당경로의 파일을 읽어내는 객체
		// FileNotFoundException은 Checked예외, 예외처리를 반드시 해야 한다.
		try {
			FileReader fr = new FileReader("helloworld.txt");	
			System.out.println("helloworld.txt 파일이 존재합니다.");
			
			int n = sc.nextInt();
		} catch(FileNotFoundException e) {
			// 파일이 존재하지 않을 경우 후처리 코드
			e.printStackTrace();
		}
	}

 

 

  1. 예외처리
  2. 예외던지기
  • 체크드예외는 예외처리후(선처리)에 예외를 다시 던진다.
  • 프로그램 흐름을 분기(예외처리의 책임)할 수 있는 메소드까지 던진다. 

 

private void test4() {
		// 프로그램 흐름을 분기하는 곳일 경우
		try {
			a();
			normalFlow();
		} catch(Exception e) {
			errorFlow();			
		}
	}
	
	public void normalFlow() {
		System.out.println("정상흐름~");
	}
	
	public void errorFlow() {
		System.out.println("오류가 발생했을 경우 흐름~");
	}
	
	public void a() throws FileNotFoundException {
		System.out.println("---- a 시작 ----");
		b();
		System.out.println("---- a 끝 ----");
	}
	
	public void b() throws FileNotFoundException {
		System.out.println("---- b 시작 ----");
		// 메소드 호출부에 예외처리 책임을 전가
		try {
			FileReader fr = new FileReader("helloworld.txt");
		} catch(Exception e) {
			System.out.println("선처리!");
			throw e; // 예외 다시 던지기 -> 프로그램 흐름을 분기할 수 있는 곳까지 던져야한다.
		}
		System.out.println("---- b 끝 ----");
	}

'학원 > 강의' 카테고리의 다른 글

*22일차 (Collection)  (0) 2022.02.23
*21일차 (파일 입출력 IO)  (0) 2022.02.22
*19일차 (문자열 자르기)  (0) 2022.02.17
*18일차 (추상클래스 / 인터페이스)  (0) 2022.02.16
*17일차(다형성 / 바인딩)  (0) 2022.02.15