본문 바로가기
학습/JAVA

10. 예외처리

by Elfen Lied 2022. 10. 25.
반응형

- 오류의 종류

  • 에러(Error)
    • 하드웨어의 잘못된 동작 또는 고장으로 인한 오류
    • 에러가 발생되면 프로그램 종료
    • 정상 실행 상태로 돌아갈 수 없음
  • 예외(Exception)
    • 사용자의 잘못된 조작 또는 개발자의 잘못된 코딩으로 인한 오류
    • 예외가 발생되면 프로그램 종료
    • 예외 처리 코드를 추가하면 정상 실행 상태로 돌아갈 수 있음

 

 

- 예외의 종류

  • 일반 예외(Exception)
    • 컴파일 체크 예외라고도 함
    • 예외 처리 코드 없으면 컴파일 오류 발생
  • 실행 예외(RuntimeException)
    • 예외 처리 코드를 생략하더라도 컴파일이 되는 예외
    • 즉 컴파일 과정에서 예외처리 코드를 검사하지 않음
    • 경험 따라 예외 처리 코드 작성 필요
public class Sample01 {
	public static void main(String[] args) throws ClassNotFoundException {
		int[] arr = {1,2,3}; // 마지막 인덱스 번호2
		System.out.println(arr[3]); // 실행예외(RuntimeException)
		
		// 일반예외 : 컴파일 전 반드시 예외처리 코드를 작성해야 함 
		test01();
	}
	
	// 메소드 밖으로 예외를 던짐
	// 메소드 밖 : 이 메소드를 호출한 메소드
	public static void test01() throws ClassNotFoundException {
			test02();
	}

	public static void test02() throws ClassNotFoundException {
		Class.forName("");
	}
}

계속 throws 하는것은 예외처리한것이 아님.

 

 

 

- 예외 클래스

 

 

- NullPointerException

  • 객체 참조가 없는 상태
    • null 값 갖는 참조변수로 객체 접근 연산자인 도트(.) 사용했을 때 발생
public class MemberVo {
	private int id;
	private String name;
	
	public MemberVo(int id, String name) {
		this.id = id;
		this.name = name;
	}

	// Getter & Setter 생성
    
	@Override
	public String toString() {
		return "MemberVo [id=" + id + ", name=" + name + "]";
	}
}

==================================================

import java.util.List;

public interface MemberDao {
	// 모든 회원 조회
	List<MemberVo> memberList();
	
	// id로 회원정보 찾기
	MemberVo findById(int id);
}

==================================================

import java.util.ArrayList;
import java.util.List;

public class MemberDaoImpl implements MemberDao {

	private List<MemberVo> memberList = new ArrayList<MemberVo>();
	
	public MemberDaoImpl() {
		memberList.add(new MemberVo(1, "김민수"));
		memberList.add(new MemberVo(2, "나민수"));
		memberList.add(new MemberVo(3, "박민수"));
		memberList.add(new MemberVo(4, "이민수"));
	}
	
	@Override
	public List<MemberVo> memberList() {
		return this.memberList;
	}

	@Override
	public MemberVo findById(int id) {
		MemberVo vo = null;
		for(MemberVo m : memberList) {
			if(m.getId() == id) {
				vo = m;
				break;
			}
		}
		if(vo == null) throw new NotFoundMemberException("존재하지 않는 회원입니다.");
		return vo;
	}

}

==================================================

public class MemberMain {
	public static void main(String[] args) {
		MemberDao dao = new MemberDaoImpl();
		try {
			MemberVo member = dao.findById(3);
			System.out.println(member.getName());

			MemberVo member2 = dao.findById(4);
			System.out.println(member2);

			MemberVo member3 = dao.findById(100);

		} catch (NotFoundMemberException e) {
			System.out.println(e.getMessage());
			System.out.println("회원 번호를 바르게 입력하세요");
		}
	}
}

==================================================

public class NotFoundMemberException extends RuntimeException {

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

데이터를 제공하는 곳에서 null를 반환한다면 Member 객체를 사용하는 곳에서 매번 null 체크를 해야 한다.

이는 호출부에서 매번 null 체크를 해야 하는 불편함이 따른다.

일반적으로 null을 반환하기보단 데이터를 제공하는 곳에서 null 체크를 하여 예외를 던지는 것이 낫다.

 

 

 

 

- ArrayIndexOutOfBoundsException

  • 배열에서 인덱스 범위 초과하여 사용할 경우 발생

 

- List<E> 사용법

배열보다 편하다.

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class MemberDemo2 {
	public static void main(String[] args) {
		String[] strArr = {"김길동", "나길동", "박길동"};
		List<String> strList = Arrays.asList("김길동", "나길동", "박길동");
		System.out.println(strList);
		
		int[] intArr = {1,2,3,4,5};
		// int의 wrapper 클래스 : Integer
		// long의 wrapper 클래스 : Long
		// double의 wrapper 클래스 : Double
		
		List<Integer> intList = Arrays.asList(1,2,3,4,5);
		intList = new ArrayList<Integer>(intList);
		System.out.println(intList);
		
		// 길이
		System.out.println("배열의 길이 : " + intArr.length);
		System.out.println("리스트의 길이 : " + intList.size());
		
		int[] result = new int[intList.size()];
		for (int i = 0; i < intList.size(); i++) {
			result[i] = intList.get(i); // intArr[i]
		}
		System.out.println(Arrays.toString(result));
		
		// 삭제
		intList.remove(2);
		System.out.println(intList); // [1, 2, 3, 4]
		
		result[2] = 0; // 배열은 삭제가 복잡하다
		System.out.println(Arrays.toString(result)); // [1, 2, 0, 4, 5]
        // 현재 상태는 삭제된 상태 아님

	}
}

 

 

 

- 예외 처리 코드(try-catch-finally)

- 예외 처리 코드

  • 예외 발생시 프로그램 종료 막고, 정상 실행 유지할 수 있도록 처리
    • 일반 예외: 반드시 작성해야 컴파일 가능
    • 실행 예외: 컴파일러가 체크해주지 않으며 개발자 경험 의해 작성
  • try – catch – finally 블록 이용해 예외 처리 코드 작성
public class Sample {
	public static void main(String[] args) {
		System.out.println("Now Loading");
		for (int i = 0; i < 50; i++) {
			Thread.sleep(200); // <======= 예외발생
			System.out.print(">");
		}
	}
}

// Thread.sleep(200) 부분에서 ctrl + 1 눌러서 
// try catch 문으로 바꿔줌

public class Sample {
	public static void main(String[] args) {
		System.out.println("Now Loading");
		for (int i = 0; i < 50; i++) {
			try {
				Thread.sleep(200);
				System.out.print(">");
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

 

- 멀티 catch 블록

  • 여러 개의 catch 블록을 하나로 합칠 수 있다. 기호 ‘|’ 로 연결할 수 있는 예외 클래스의 개수는 제한이 없다.
  • 연결된 예외 클래스 간의 상속 관계가 존재하면 컴파일 에러가 발생한다.ㅌ

 

- catch 순서

  • 상위클래스 예외가 하위클래스 예외보다 아래쪽에 위치 해야 한다.
import java.util.Scanner;

public class CatchOrderDemo {
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		System.out.print(">>회원번호 입력");
		
		try {
			String inputValue = scan.nextLine();
			int id = Integer.parseInt(inputValue);
			System.out.println("입력한 번호 : " + id);
			System.out.println("finally1");
			System.out.println("finally2");
			System.out.println("finally3");
		}  catch (NumberFormatException e) {
			System.out.println("숫자를 입력하세요");
		}catch (RuntimeException e) {
			System.out.println("실행 예외 발생");
		} catch (Exception e) {
			System.out.println("일반 예외 발생");
			System.out.println(e.getMessage());
		} finally { 
			// 예외가 처리가 안되더라도 finally 블록은 실행됨
			// finally 블록에는 리소스 반납하는 코드 작성 
			scan.close();
		}
	}
}
반응형

댓글