[Java] 예외처리

devheyrin·2022년 8월 27일
1

JavaBasic

목록 보기
5/6

예외처리

  • 개발자가 예측 가능한 문제 상황에 대한 처리 방법을 명시해두는 것
  • 프로세스 중 어떤 부분에서 문제가 생겼는지 파악하기 위해 사용한다.
  • IO 관련해서는 예외처리가 필수이다.

형식

  • 자식클래스는 부모클래스로 치환되기 때문에, 자식클래스를 부모클래스보다 위쪽에 배치해야 한다.
try {
	// 예외가 발생할 것으로 예측되는 명령 
} catch (예외클래스타입1 변수명){
	// 예외클래스타입1 발생시 수행할 명령
} catch (예외클래스타입2 변수명){
	// 예외클래스타입2 발생시 수행할 명령 
} finally {
	// 무조건 실행해야 하는 명령 
}

예외 발생 이후의 명령은 실행되지 않는다.

try {
			System.out.println(3);
			System.out.println(0/0); // 예외발생!!!
			System.out.println(4); // 예외발생 이후의 명령은 실행되지 않음 
		} catch (ArithmeticException e) {
			// TODO: handle exception
			System.out.println(5);
		}finally {
			System.out.println(6);
		}

// 결과 
3
5 
6

예외 만들어 던지기

  • new Exception - 예외 객체 생성, 인자로 넣어준 메시지가 예외메시지가 된다.
  • throw - 예외 던지기(발생시키기)
try {
			throw new Exception("고의로 예외발생");
		} catch (Exception e) {
			System.out.println("에러 메시지: " + e.getMessage());
			e.printStackTrace();
			// 스택을 확인하는 명령 
			// 스택에는 지금까지 실행한 명령들이 쌓임 
			// java.lang.Exception: 고의로 예외발생
			// at exception.ExceptionEx2.main(ExceptionEx2.java:7)
		}
		System.out.println("프로그램 정상 종료");

숫자 게임 - 예외처리

  • 예외가 발생할 수 있는 코드부분에만 try를 씌운다.
		int answer = (int)(Math.random() * 100) + 1;
		int input = 0; // 사용자가 입력 
		int count = 0; // 시도 횟수 카운트 
		
		
		do {
			count++;
			System.out.println("1~100사이의 값을 입력하세요 : ");
			
			try {
				input = new Scanner(System.in).nextInt();
				// 예외처리시에는 Scanner객체를 반복문 안에서 생성한다. 
			} catch (InputMismatchException e) {
				System.out.println("입력이 잘못됨");
				continue;
			}

			if (input == answer) {
				System.out.println("정답!");
				System.out.println("시도 횟수 : " + count);
				break;
			} else if (input < answer) {
				System.out.println("up");
				System.out.println("시도 횟수 : " + count);
				continue;
			} else if (input > answer) {
				System.out.println("down");
				System.out.println("시도 횟수 : " + count);
				continue;
			}

		} while (true);

PrintStackTrace 의 stack - 자료구조

Queue

  • First In First Out (선입선출)

Stack

  • Last In First Out (후입선출)
  • 일반적인 프로그램, 네트워크의 자료 구조

메소드를 호출한 사람에게 예외 던지기(책임전가)

  • 예외를 던지는 메소드 만들기
public class Rectangle {
	private int width;
	private int heigth;
	public Rectangle(int width, int height) throws Exception {
		if (width <= 0 || height <= 0) {
			throw new Exception("넓이 또는 높이의 값이 잘못되었습니다");
		} 
		this.width = width;
		this.heigth = height;	
	}
	
	int getArea() {
		return width *heigth;
	}
}
  • main 에서 메소드 호출하기
    • throw 로 JVM에게 책임전가하거나
    • try - catch 로 예외를 처리해주어야 한다.
public class RectangleMain {
	public static void main(String[] args) {
		Rectangle r = null;
		
		try {
			r = new Rectangle(5, 98);
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
		
		int area = r.getArea();
		System.out.println("넓이: " + area);
	}

}

사용자 정의 예외 만들기

  • 예외 클래스 직접 만들기
    • Exception을 상속하면 Catch에 사용할 수 있는 예외 클래스가 된다.
public class AgeInputException extends Exception {
	public AgeInputException() {
		super("유효하지 않은 나이가 입력되었습니다.");
	}
}
public class NameLengthException extends Exception {
	String name;
	
	public NameLengthException(String name) {
		super("잘못된 이름이 입력되었습니다.");
	}
	
	public void showWrongName() {
		System.out.println(this.name + "은(는) 잘못된 이름입니다.");
	}

}
  • 예외 사용하기
public class PersonalInfo {
	String name;
	int age;
	
	public PersonalInfo(String name, int age) {
		this.name = name;
		this.age = age;
	}
	
	public void showPersonalInfo() {
		System.out.println("이름: " + this.name);
		System.out.println("나이: " + this.age);
	}
}
import java.util.Scanner;

public class UserExceptionMain {
	public static Scanner sc = new Scanner(System.in); 
	// Scanner 객체는 static에 올려두고 사용
	
	public static void main(String[] args) {
		
		try {
			PersonalInfo info = readPersonalInfo();
			info.showPersonalInfo();
		} catch (AgeInputException e1) {
			e1.printStackTrace();
		} catch (NameLengthException e2) {
			e2.showWrongName(); // 00은(는) 잘못된 이름입니다. 
			e2.printStackTrace();
		}
		
	}
	
	// 이름, 나이를 입력받아 PersonalInfo객체를 리턴하는 함수 
	public static PersonalInfo readPersonalInfo() throws AgeInputException, NameLengthException {
		String name = readName();
		int age = readAge();
		return new PersonalInfo(name, age);
	}
	
	// 나이 입력받아 검증 후 예외를 던지는 함수
	public static int readAge() throws AgeInputException{
		System.out.println("나이 입력: ");
		int age = sc.nextInt();
		if (age < 0) {
			throw new AgeInputException();
		}
		return age;
	}
	
	// 이름 입력받아 검증 후 예외를 던지는 함수 
	public static String readName() throws NameLengthException {
		System.out.println("이름 입력: ");
		String name = sc.nextLine();
		if (name.length() < 2 || name.length() > 4) {
			throw new NameLengthException(name);
		}
		return name;
	}

}

printStackTrace

  • 호출된 메소드 순서대로 제일 아래쪽부터 쌓인다.
exception.AgeInputException: 유효하지 않은 나이가 입력되었습니다.
	at exception.UserExceptionMain.readAge(UserExceptionMain.java:41)
	at exception.UserExceptionMain.readPersonalInfo(UserExceptionMain.java:32)
	at exception.UserExceptionMain.main(UserExceptionMain.java:19)

이너 클래스, Inner Class, Nested Class

  • 이벤트 처리에 많이 사용
class A { // A.java
	class B { // A$B.java
	}
}
  • 이름 없는 클래스를 가장 많이 사용!

Outer - Inner 예제

public class Outer {
	class Inner {
		void jababa() {
			System.out.println("잡아바");
		}	
	}
}
public class OuterMain {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		/*
		 * Outer o = new Outer(); 
		 * Outer.Inner in = o.new Inner(); // Outer.Inner 타입
		 * in.jababa();
		 */
		
		// 2줄
		/*
		 * Outer.Inner in = new Outer().new Inner(); 
		 * in.jababa();
		 */
		
		
		// 1줄 
		new Outer().new Inner().jababa();
	
	}

}

PiggyBank 예제

public class PiggyBank {
	
	int total;
	Slot slot; // 저금통 입구 
	
	public PiggyBank() {
		total = 0;
		slot = new Slot();
	}
	
	
	class Slot {
		void put(int amount) {
			total += amount;
		}
	}

}
public class PiggyBankMain {
	public static void main(String[] args) {
		
		PiggyBank bank1 = new PiggyBank();
		PiggyBank bank2 = new PiggyBank();
		PiggyBank bank3 = new PiggyBank();
		
		bank2.slot.put(1000);
		bank3.slot.put(2000);
		bank3.slot.put(2000);
		
		System.out.println("첫 번째 저금통: " + bank1.total);
		System.out.println("두 번째 저금통: " + bank2.total);
		System.out.println("세 번째 저금통: " + bank3.total);
	}

}
profile
개발자 헤이린

0개의 댓글