1010 (17일차) 예외처리
실습문제 1,2,3,4 피드백 完
예외처리(Exception)
:에러 - 해결할 수 없는 심각한 오류 - 재실행
:예외처리 - 분기에 따라 정상적으로 복구 가능
비정상적인 종료를 예외처리를 통해 정상흐름으로 돌려놓음
타입 | Error | Exception |
개념 | -치명적인 오류 -회복 불가능,예외처리 사용 불가 |
-회복가능한 오류 -예외처리를 사용할 수 있음 |
종류 | 메모리가 소진되는 오류 OutOfMemoryError :heap영역 메모리 소진 ex)배열크기가 integer 최댓값 StackOverFlowError :stack영역 메모리 소진 ex)잘못된 재귀함수 (함수가 자기자신을 무한 호출) |
InputMismatchException 타입 불일치 오류 ex)정수값받아야하는데 문자열값 대입 ArithmeticException 어떠한 수를 0으로 나눌때 오류(불능) ex) 100/0 NullPointerException null인 값을 사용하는 경우 ex)str = null; str.length() 그 외 인덱스 오류인 ArrayIndexOutOfBoundsException IndexOutOfBoundsException 등등.. |
컴파일 에러(compilie time) / 런타임 에러 : 에러 발생시기에 따라 구분.
컴파일:잘못된 구문 작성 시 발생
런타임:스캐너 에러
시스템 에러: 컴퓨터 오작동 소스구문으로 해결 불가
unchecked 예외 | checked 예외 | |
실행 시점 | 코드 상 문제 없음. 실행 시(runtime) 발생 |
컴파일 단계에서 발생. 에러나는 라인을 알려줌. |
종류 | RuntimeException 포함 후손들 | RuntimeException들을 제외한 나머지. |
예시 | Scanner로 정수값을 입력받으려 하는데 문자열이나 다른 것을 입력받을 경우, InputMismatchException 발생 |
FileReader로 특정 txt파일을 읽어오려고 할때 코드 작성 시 에러발생. throws 나 try-catch 사용해야 함. |
try ~ catch ~ finally
1.구조
try
{
오류 발생 가능성 코드(안 날 수도있음)
}
catch(Exception e)
{
오류 발생 시 실행
}
finally
{
오류 유무와 상관없이 실행됨 (조기 리턴할때도 실행됨)
}
/**
* try - catch 블럭 실행 순서
*
*/
private void test3() {
System.out.println(1);
try
{
System.out.println(2);
if(true) return;//조기리턴
String str = null;
str.length();
System.out.println(3);
}
catch (NullPointerException e )
{
System.out.println(4);
}
finally
{
//try절의 예외 발생여부와 관계없이 무조건 실행
System.out.println(100); //중간에 조기리턴이 있어도 무조건 실행
}
System.out.println(5);
}
2.다형성
자식객체를 부모타입으로 제어try catch문 사용시, catch 때 여러 Exception 사용 가능하다.
단! 자식->부모 순으로 사용해야함.
오류마다 다른 처리를 하고싶다면 상위 클래스를 맨 아래에 두고 내가 원하는 예외처리를 상단에 두자
/**
* catch절의 다형성
* - 자식객체를 부모타입으로 제어
* - 자식/부모 타입의 catch 블럭을 나열 할 때는 자식-부모 순으로 작성해야한다.
*/
private void test4() {
try
{
System.out.print("정수 입력:");
int m = sc.nextInt();
System.out.println(m);
String str = null;
System.out.println(str.length());
}
// catch(InputMismatchException e)
// {
// System.out.println("정수만 입력 가능합니다..");
// System.out.println(e);
// }
// catch(NullPointerException e)
// {
// System.out.println("str는 null일 수 없다.");
// System.out.println(e);
// }
catch(RuntimeException e)
{
System.out.println("Runtime........:"+e);
//혹은 위에 주석처리 풀린 것 버전으로도 가능.셋중 먼저 걸린 catch문으로 사용
//단 부모타입은 맨 뒤에 둬야함.
}
catch(Exception e)
{
System.out.println("Exception.......:"+e);
}
}
if~else문을 사용하지 않고 분기 처리가 가능하다.(throw 예외 던지기)
-try문 안에 예외가 발생할 가능성이 있는 코드를 넣는다.
-checkAge2()에서 입력한 정수값을 나이로 받고 20살 미만/이상인지 판단
예외가 발생한다면 throw new underAgeException 이라는 커스텀 익셉션을 던진다.
나이가 20세 미만이면 다시 함수호출부로 돌아와서 바로 catch문을 실행
미성년자라 게임을 할 수 없다 문구 출력.
/**
* 예외 던지기를 통한 분기 흐름 만들기
*/
private void test2()
{
try
{
checkAge2(); //미성년자인 경우 예외처리
System.out.println("게임을 시작합니다.😜😜");
}
catch(Exception e)
{
System.out.println("미성년자는 게임을 할 수 없습니다.😰😰😰😰");
System.out.println(e.getMessage()); //("미성년자 : "+ age+"세");
}
}
private void checkAge2()
{
System.out.print("나이 입력 : ");
int age = sc.nextInt();
if(age < 20)
throw new underAgeException("미성년자 : "+ age+"세"); //underAgeException
//던져진 예외는 checkAge2를 호출한 곳으로 돌아간다
}
custom Exception - underAgeException
기본생성자 포함 super class 생성자를 만들어준다. 끝.
package sh.java.exception;
public class underAgeException extends RuntimeException
{
public underAgeException() {
super();
// TODO Auto-generated constructor stub
}
public underAgeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
// TODO Auto-generated constructor stub
}
public underAgeException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
public underAgeException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
public underAgeException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}
}
예외 미루기 (Throws)
RuntimeException과 관계없는 모든 클래스
예외처리(try catch) 강제화 즉, 예외처리를 하지 않으면 컴파일 오류 유발
우회적인 처리를 강제화 할 목적으로 입/출력 관련 메소드 등에서 쉽게 확인
(추상클래스와 비슷하다)
예외처리 혹은 예외회피 둘 중 하나는 반드시 해야함
주의사항:
예외처리를 미루다가
main함수에 throws를 걸 수도 있는데, 이건 예외처리를 안한거나 마찬가지.
실행하면 오류발생함. 제 때 예외처리를 해두는게 좋다.
package sh.java.exception;
import java.io.FileNotFoundException;
import java.io.FileReader;
/**
*
* 2023-10-10
* checked Exception
* -Exception 후손 클래스 중에서 RuntimeException와 관계없는 모든 클래스
* -예외처리(try-catch)를 강제화
* -즉, 예외처리 안하면 컴파일 오류 유발
* -우회적인 처리를 강제화 할 목적으로 입/출력관련 메소드 등에서 쉽게 확인 가능
* -예외처리(try catch) 또는 예외회피(throws) 둘 중 하나는 반드시 해야함
*
*/
public class ThrowsExceptionStudy {
//main에서 예외처리 던져버리면 오류발생함(더 이상 던져줄 곳이 없음) 예외처리 안한거랑 같음
public static void main(String[] args)//throws FileNotFoundException //throws FileNotFoundException
{
ThrowsExceptionStudy study = new ThrowsExceptionStudy();
try
{
study.test1();
}
catch(Exception e)
{
e.printStackTrace();
}
//study.test1();
System.out.println("정상종료");
}
//예외회피:예외처리의 의무를 메소드 호출부로 미룸
private void test1() throws FileNotFoundException
{
//예외처리
// try
// {
// FileReader fr = new FileReader("abc.txt");
// }
// catch(FileNotFoundException e)
// {
// e.printStackTrace();
// }
FileReader fr = new FileReader("abc.txt");
}
}
예외처리로 해결 할 수있는 일은 무궁무진하다.
잘못 된 부분이 어디인지,(런타임은 조금 어려울지도)
무슨 오류인지도 알려주기 때문에 긴가민가하다면 쓰는 것이 좋을 것 같다.