[JAVA]20일차(예외(Exception) 처리 개요)

정효진·2021년 8월 11일
0

Developer Study

목록 보기
35/47
post-thumbnail

8월11일(수)

Test140~Test151

◼ 예외(Exception) 처리

//자바의 정석 p.414
//어려워도 당황하지마! 원래그래

▪ 프로그램에서 발생하는 오류는

① 잘못된 문법을 사용하거나 변수 등을 정의하지 않은 상태에서
사용함으로써 컴파일 단계에서 발생하는 문법적인 오류

② 프로그램을 실행하는 과정에서 발생되는 런타임 오류
로 나눌 수 있다.

  • 개발자가 문제 분석을 잘못하거나 실수에 의해 엉뚱한 결과를 가져오게 되는 논리적인 오류와

  • 시스템 이상에서 발생되는 시스템 오류, 그리고

  • 프로그램 실행 중 발생되는 비정상적인 상황을 의미하는 예외사항(Exception)이 있다.

예를 들어,
→ 어떤 수를 0으로 나누거나...
→ 배열 첨자를 벗어나는 상황이 발생하거나...
→ 존재하지 않은 파일을 오픈하여 읽어들인다거나...

==> 개발자가 이런 예외 사항이 발생할 경우를 미리 예측하여
적절히 대응하기 위한 절차를 구현하도록 문법을 정리해 놓은 것.
예.외.처.리.

※ 정리해 놓은 문법~!!!(→ Exception 클래스)

  • 예외는 프로그램 실행 중에 발생할 수 있는 명령어의 정상적인 흐름을 방해하는 이벤트로 자바에서 예외는 하나의 오브젝트(Object, 객체)이다.

  • 프로그램 실행 중에 메소드 안에서 오류가 발생하게 될 경우, 메소드는 그 오류에 해당하는 예외 오브젝트를 만들고 그것을 자바 런타임 시스템(Runtime System)에 전달해 준다.

  • 자바에서의 모든 예외는 Throwable 클래스나 Throwable 클래스의 하위 클래스를 상속받아 사용한다.

  • Throwable 클래스는 예외를 설명하는 문장이나 예외가 발생할 때의 프로그램의 상태에 관한 정보를 포함하고 있다.

  • Throwable 클래스에서 파생된 클래스

▪ Exception 클래스
Exception 예외 클래스는 일반적으로 프로그래머에 의해
복원될 수 있는 예외 상황으로
메소드가 실행 중에 던지는 예외를 가리킨다.

▪ Error 클래스
심각한 예외의 형태로 개발자가 복원할 수 없는 형태의 예외이다.

▪ 예외의 종류

  • checked exception
    메소드 내에서 예외가 발생한 경우 메소드를 정의할 때 『throws』문에 메소드 내에서 발생할 수 있는 예외들을 명시해주거나 또는 그 예외를 『try~catch』해서 처리해주어야만 하는 예외이다.
    컴파일러가 컴파일 하는 과정에서 『checked exception』이 『throws』 되는가의 여부 혹은 『try~catch』되는지의 여부를 판단하여 프로그램에서 예외를 어떤 방식으로 처리하지 않으면 컴파일 자체가 불가능하다.

  • unchecked excepion
    사전에 처리하지 않아도 컴파일러가 체크하지 않은 런타임 시에 발생할 수 있는 예외이다.

▪ java.lang.Trowable 클래스의 주요 메소드

  • String toString()
    : Throwable 각각에 대한 설명을 문자열 형태로 반환한다.

  • void printStackTrace(printStream s)

  • void printStackTrace(printWriter w)
    : 표준 출력 스트림에 스택 호출 목록을 마지막 메소드부터 출력한다.

  • .getMessage() = 에러 이벤트와 함께 들어오는 메세지를 출력한다.

  • .toString() = 에러 이벤트의 toString()을 호출해서 간단한 에러 메시지를 확인한다.

  • .printStackTrace() = 에러 메세지의 발생 근원지를 찾아서 단계별로 에러를 출력한다.

▪ 주요 런타임 예외 클래스

  • ArithmeticExcepion
    : 수치 계산상의 오류
  • ArrayStoreException
    : 배열에 잘못된 데이터 형을 저장하려 했을 경우 발생하는 오류
  • IndexOutOfBoundsException
    : 배열, 문자열, 벡터 등에서 인덱스 범위가 벗어난 경우 발생하는 오류
  • ClassCastException
    : 클래스 변환을 잘못한 경우 발생하는 오류
  • NullPointerException
    : 빈 객체를 참조하는 경우(초기화 되지 않은 변수 사용 등)
    발생하는 오류
  • SecurityException
    : 자바의 내부 보안 사항을 위반하였을 경우 발생하는 오류

▪ 예외(Exception) 처리 코드 설명📝

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

public class Test143_1
{										//---------[예외 처리하는 방법 ①]: throws IOException로 던지기
	public static void main(String[] args) throws IOException
	{
		//BufferdReader 인스턴스 생성
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		// 주요 변수 선언
		int a, b, c;


		//-----------------[예외 처리하는 방법 ②] : try-catch 구문에 문제될 부분 넣기
		/*
		try
		{
			System.out.print("첫 번째 정수 입력 : ");
			a = Integer.parseInt(br.readLine());
			System.out.print("두 번째 정수 입력 : ");
			b = Integer.parseInt(br.readLine());
			//error: unreported exception IOException; must be caught or declared to be thrown 
			//                  ---------------------

			c = a + b;

			System.out.println("결과 : " + c);


		}
		catch (IOException e)  //IOException을 이름붙여서(e)
		{
			// IOExcepiton → checked exception
			//-- 메소드를 정의하는 과정에서 throws 한 예외
			// 잡아내거나 던지지 않을 경우 컴파일 에러 발생.
			System.out.println(e.toString());   //별도로 처리하겠다! 여기선 toString 함
		}
		*/

		
		//----------------- [예외 처리하는 방법 ③] : 숫자형태 이외에 값 입력
		/*
		try
		{
			System.out.print("첫 번째 정수 입력 : ");
			a = Integer.parseInt(br.readLine());
			System.out.print("두 번째 정수 입력 : ");
			b = Integer.parseInt(br.readLine());
			
			c = a + b;

			System.out.println("결과 : " + c);


		}
		catch (IOException e1)  //IOException을 이름붙여서(e)
		{
			// IOExcepiton → checked exception
			//-- 메소드를 정의하는 과정에서 throws 한 예외
			// 잡아내거나 던지지 않을 경우 컴파일 에러 발생.
			System.out.println(e1.toString());   //별도로 처리하겠다! 여기선 toString 함
		}
		catch(NumberFormatException e2)
		{
			System.out.println(e2.toString());
			System.out.println("숫자 형태의 데이터를 입력해야 합니다~!!!");
		}
		
		// catch 되서 처리되고 있음!
		//첫 번째 정수 입력 : abc
		//java.lang.NumberFormatException: For input string: "abc"
		//숫자 형태의 데이터를 입력해야 합니다~!!!
		//계속하려면 아무 키나 누르십시오 . . .
		*/

		//----------------- [예외 처리하는 방법 ④] : catch 안에 한번에 처리 e.printStackTrace()사용
		/*
		try
		{
			System.out.print("첫 번째 정수 입력 : ");
			a = Integer.parseInt(br.readLine());
			System.out.print("두 번째 정수 입력 : ");
			b = Integer.parseInt(br.readLine());
			//error: unreported exception IOException; must be caught or declared to be thrown 
			//                  ---------------------

			c = a + b;

			System.out.println("결과 : " + c);


		}
		catch (IOException e)  //IOException을 이름붙여서(e)
		{
			System.out.println(e.toString());   //별도로 처리하겠다! 여기선 toString 함
			System.out.println(e.getMessage());

			System.out.println("pringStackTrace...");
			e.printStackTrace();
		}
		*/

		//----------------- [예외 처리하는 방법 etc...]s : finally사용
		try
		{
			System.out.print("첫 번째 정수 입력 : ");
			a = Integer.parseInt(br.readLine());
			System.out.print("두 번째 정수 입력 : ");
			b = Integer.parseInt(br.readLine());
			//error: unreported exception IOException; must be caught or declared to be thrown 
			//                  ---------------------

			c = a + b;

			System.out.println("결과 : " + c);


		}
		catch (IOException e)  //IOException을 이름붙여서(e)
		{
			// IOExcepiton → checked exception
			//-- 메소드를 정의하는 과정에서 throws 한 예외
			// 잡아내거나 던지지 않을 경우 컴파일 에러 발생.
			System.out.println(e.toString());   //별도로 처리하겠다! 여기선 toString 함
		}

		finally  //check~!!!
		{
			// 예외가 발생하거나 발생하지 않거나...
			// 언제나 실행되는 영역~!!!

			System.out.println("고생 많으셨습니다. 점심 맛있게 먹읍시다.");
		}



	}
}

▪ 이름 입력[종료:Ctrl+z] 예외(Exception) 처리 코드 설명📝

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;


public class Test144 
{

	private String[] date = new String[3];


	public void proc() throws IOException  //-- readLine() 때문에 throws 입력!
	{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		String str;
		int n = 0;

		System.out.print("이름 입력(종류:ctrl+z) : ");

		
		//   원래는 오른쪽부터인데 괄호로 묶은것 먼저
		while ((str = br.readLine()) != null)         //-- readLine() 때문에 throws 안해주면 에러 발생!
		{                         //-------- == ctrl+z 
			date[n++] = str;
			System.out.print("이름 입력(종류:ctrl+z) : ");
		}

		System.out.println("입력된 내용...");
		for(String s : date)
		{
			if(s != null)
			{
				System.out.println(s);
			}
		}
	}

	public static void main(String[] args) throws IOException
	{
		Test144 ob = new Test144();
		ob.proc();
	}
}


// 배열이 3갠데 4개 넣으려고하니까 에러발생 -> 이건 unchecked excepion

▪ 이름 입력[종료:Ctrl+z] try-catch 예외 처리 사용 코드 설명📝

//Test144같은데 try-catch사용 -> 내부적으로 예외를 잡아버려서 throws IOException을 메인에 안해도 됨!!

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;


public class Test145
{

	private String[] date = new String[3];


	public void proc() //throws IOException  //-- readLine() 때문에 throws 입력!
	{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		String str;
		int n = 0;

		try
		{
			System.out.print("이름 입력(종류:ctrl+z) : ");

		
			//   원래는 오른쪽부터인데 괄호로 묶은것 먼저
			while ((str = br.readLine()) != null)         //-- readLine() 때문에 throws 안해주면 에러 발생!
			{                         //-------- == ctrl+z 
				date[n++] = str;
				System.out.print("이름 입력(종류:ctrl+z) : ");
			}

			System.out.println("입력된 내용...");
			for(String s : date)
			{
				if(s != null)
				{
					System.out.println(s);
				}
			}
		}
		catch (IOException e)
		{
			System.out.println(e.toString());
		}
		catch (ArrayIndexOutOfBoundsException e)
		{
			System.out.println("예외 발생~!!!");
			System.out.println("getMessage : " + e.getMessage());
			System.out.println("toString   : " + e.toString());
			System.out.println("printStackTrace...........");
			System.out.println();

			//이름 입력(종류:ctrl+z) : 정효진
			//이름 입력(종류:ctrl+z) : 김효진
			//이름 입력(종류:ctrl+z) : 박효짐
			//이름 입력(종류:ctrl+z) : 마효진
			//예외 발생~!!!
			//getMessage : 3
			//toString   : java.lang.ArrayIndexOutOfBoundsException: 3
			//printStackTrace...........

			//계속하려면 아무 키나 누르십시오 . . .
		}

		
	}

	public static void main(String[] args) //throws IOException
	{
		Test145 ob = new Test145();
		ob.proc();
	}
}

▪ Test147 / Test148 파일과 비교📝

Test147

class Demo
{
	private int value; //기본적으로 0으로 초기화 되니까 -3 넣어도 0나옴

	public void setValue(int value)
	{
		if(value<=0)

			return;	//-- 종료 → 메소드 종료

		this.value = value;
	}



	public int getValue()
	{
		return value;
	}
}

public class Test146
{
	public static void main(String[] args)
	{
		Demo ob = new Demo();
		ob.setValue(-3);
		int result = ob.getValue();
		System.out.println(result);
	}
}

Test148

class Demo2
{
	private int value;

	public void setValue(int value) throws Exception   //check~!!!   Exception 은 lang패키지에 있어서 import생략 가능한~!
	{
		if(value<=0)
		{
			// 예외 생성(발생) - 폭발물 제작을 여기서 한 것!
			throw new Exception("value 는 0보다 작거나 같을 수 없습니다.");
			// throw 예외를 발생시킬때 사용하는 키워드!!   ==> 이렇게 실행하면 에러! throws Exception 작성해줘야함!!
		}

		this.value = value;
	}

	public int getValue()
	{
		return value;
	}
}

public class Test147
{
	public static void main(String[] args) //throws Exception   //check~!!!  이렇게 해주던지 아니면 try-catch로 잡아내!
	{
		Demo2 ob = new Demo2();

		try
		{
			ob.setValue(-3);
			int result = ob.getValue();
			System.out.println(result);
		}
		catch (Exception e)  // checked Exception
		{
			System.out.println(e.toString());
		}
		
	}
}
/*
java.lang.Exception: value 는 0보다 작거나 같을 수 없습니다.
계속하려면 아무 키나 누르십시오 . . .
*/

▪ 예외 다시 던지기 코드📝

public class Test148
{
	public static void main(String[] args)
	{
		Test148 ob = new Test148();

		try
		{
			int a = ob.getValue(-2);     // ⑥ 예외 발생
			System.out.println("a : " + a);
		}
		catch (Exception e)              // ⑦ 예외 잡아내기
		{
			System.out.println("ⓑ printStackTrace.......");
			e.printStackTrace();
		}
		
	}

	public int getData(int data) throws Exception
	{
		if (data<0)
			throw new Exception("date 가 0보다 작습니다.");
			// ① 예외 발생  --> 그래서 던지기로 함(throws Exception) -> 이러면 getValue 로 떨어짐

		return data + 10;
	}

	public int getValue(int value) throws Exception
	{
		int a = 0;

		try
		{
			a = getData(-2);  // ② 예외발생 -> 그래서 예외를 catch로 잡음 근데 왜?? throws Exception을 썼나?
		}
		catch (Exception e)   // ③ 예외 잡아내기
		{
			// ④ 잡아낸 예외에 대한 처리
			System.out.println("ⓐ printStackTrace............");
			e.printStackTrace();

			// ⑤ 잡아낸 예외를 다시 던지기
			throw e;  //이거 주석하면 throws Exception 없어도됨
			//-- 주석 처리 시(즉, 잡아낸 예외를 다시 던지지 않을 경우)
			//   main() 메소드의 예외 처리 구문은 수행되지 않게 된다.
		}

		return a;
	}
}

/*
ⓐ printStackTrace............
java.lang.Exception: date 가 0보다 작습니다.
        at Test148.getData(Test148.java:29)
        at Test148.getValue(Test148.java:41)
        at Test148.main(Test148.java:15)
ⓑ printStackTrace.......
java.lang.Exception: date 가 0보다 작습니다.
        at Test148.getData(Test148.java:29)
        at Test148.getValue(Test148.java:41)
        at Test148.main(Test148.java:15)
계속하려면 아무 키나 누르십시오 . . .

*/

▪ 다른 예외 다시 던지는 예외처리 코드(빨간폭발물/파란폭발물)📝

public class Test149
{
	public int getValue(int value)  throws Exception            // ⑦ 예외 던지기(파란 폭발물)
	{
		int a = 0;

		try
		{
			a = getData(-2);									//③ 예외 발생	
		}														//   빨간 폭발물
		catch (Exception e)										//④ 예외 잡아내기
		{														//   빨간 폭발물
			// ⑤ 예외 처리(빨간 폭발물)
			System.out.println("printStackTrace..............");
			e.printStackTrace();
			
			// ⑥예외 생성
			throw new Exception("value 가 음수입니다.");        
			// 아까는 같은 e던지는 거였는데 지금은 새로운 예외 발생!
			// (파란 폭발물)
		}

		return a;
	}

	public int getData(int data) throws Exception                //② 예외 던지기
	{															 //   빨간 폭발물
		if(data<0)
			throw new Exception("date 가 0 보다 작습니다.");     //① 예외 발생
																 //   빨간 폭발물
		return data + 10;
	}
	
	public static void main(String[] args)      // ⑨
	{
		Test149 ob = new Test149();

		try
		{
			int a = ob.getValue(-1);                                //⑧ 예외 발생 //파란 폭발물
			System.out.println("a: " + a);
		}
		catch (Exception e)								     		// ⑨ 예외 잡아내기  //파란 폭발물
		{
			// ⑩ 예외 처리(파란 폭발물)
			System.out.println("printStackTrace..............");
			e.printStackTrace();
		}
		
	}
}
profile
개발새발

0개의 댓글