1. 예외처리 ( exception handling )
1) 예외(exception)?
- 일반적으로 에러(error)라고 불리우는 사건이다.
- 예외가 발생되면 프로그램이 '비정상 종료' 된다.
2) 예외처리 ( exception handling )?
- 예외가 발생되면 '비정상종료' 되는데, 비정상 종료되는 프로그램을
'정상 종료' 하도록 처리하는 방법이다.
- 정상종료 처리방법은 사용자에게 문제발생 이유를
알려주는 방법( 콘솔 또는 경고창 )도 포함됨.
사용자가 이해하기 쉽도록 친절하게 알려줘야 한다. (ex) 한국어 )
- 잘못 알고 있는 경우는 문제발생된 상황을 해결해주는 것이 아니다.
( 불가능 함 )
문제발생된 코드는 어쩔수 없이 실행이 안되고 이후의 코드를 실행해서
main 끝까지 가도록 하는 작업이 개발자가 해야되는 예외처리이다.
package exam20_exception;
public class ExceptionTest01 {
public static void main(String[] args) {
System.out.println("----- 프로그램 시작 -----");
// 정상종료
int n = 2;
int result = 10 / n;
System.out.println("1. 결과값: " + result); // >>> 5
// 비정상종료
int n2 = 0;
int result2 = 10 / n2;
System.out.println("2. 결과값: " + result2);
/*
* >>>
----- 프로그램 시작 -----
Exception in thread "main" java.lang.ArithmeticException: / by zero
at exam20_exception.ExceptionTest01.main(ExceptionTest01.java:15)
*/
// * 예외가 발생했으니 프로그램종료 멘트까지 가도록 예외처리를 해줘야한다.
System.out.println("----- 프로그램 종료 -----");
}
}
3) 예외처리 방법
가. 예외 클래스 제공 (* 이미지 참고 )
Object
|
Throwable
-> Error: 개발자가 핸들링 불가
-> Exception ( * 예외처리시 사용하는 예외클래스의 최상위 )
1) Runtime Exception( 런타임계열: 런타임시(실행) 발생, 컴파일 unchecked 계열 )
ArithmeticException( ex) 10/0 )
ClassCastException (ex) 클래스 형변환시)
NullPointerException
(ex) null 값을 가진상태로 메서드 호출시
ArrayIndexOutOfBoundsException
(ex) 없는 배열요소 접근시
........
2) IOException, SQLException ( 비런타임계열: 컴파일시 발생, 컴파일 checked 계열 )
FileNotFoundException
.......
나. 예외클래스 + try ~ catch ~ finaly 문
- 예외가 발생된 곳에서 처리하는 방법이다.
- 문법:
{ // start main
...
try {
실행문1;
실행문2;
} catch ( 예외클래스1 변수 ) {
// 적합한 예외클래스를 지정(권장)
// 다형성 가능(비권장)
예외발생시 처리하는 문장;
} catch ( 예외클래스2 변수 ) {
// Exception 최상위 클래스는 반드시 가장 마지막에 지정한다.
// 즉, 계층구조의 자식부터 catch 해야 된다. ( 컴파일 에러 발생 )
예외발생시 처리하는 문장;
} finally {
반드시 수행되는 문장; ( 파일 및 DB 연동시 close 작업)
}
문장;
문장;
....
} // end main
- 예외관련 정보 제공
e.printStackTrace( ); ==> 자체적으로 print 가능, 예외발생메세지,
예외발생 line 정보, 예외클래스 정보 등 제공함.
개발시 디버깅용으로 사용됨.
sysout( e.getMessage( ) ) ==> 예외발생메세지 제공.
- try~finally 문 가능 ( catch 문 없이 사용 가능 )
==> 예외처리 목적이 아닌 반드시 실행해야 되는 문장을 알려주는 용도로
사용된다.
ex)
try {
} finally {
}
package exam20_exception;
public class ExceptionTest02_try_catch {
public static void main(String[] args) {
System.out.println("----- 프로그램 시작 -----");
try {
// 정상종료
int n = 2;
int result = 10 / n;
System.out.println("1. 결과값: " + result); // >>> 5
// 비정상종료
int n2 = 0;
int result2 = 10 / n2;
System.out.println("2. 결과값: " + result2);
} catch (ArithmeticException arithmeticException) {
// 예외처리 코드구현 ==> 사용자에게 친절하게 예외 메세지를 알려주는 것이다.
// 아무 예외클래스가 아닌 적합한 예외클래스 지정. 다형성 가능
// 다형성 : RuntimeException , Exception ,... (권장안함)
System.out.println("ArithmeticException: 0 으로 나누어 예외가 발생됨.");
}
System.out.println("----- 프로그램 종료 -----");
}
}
package exam20_exception;
public class ExceptionTest02_try_catch2_예외메세지제공 {
public static void main(String[] args) {
System.out.println("----- 프로그램 시작 -----");
try {
// 정상종료
int n = 2;
int result = 10 / n;
System.out.println("1. 결과값: " + result); // >>> 5
// 비정상종료
int n2 = 0;
int result2 = 10 / n2;
System.out.println("2. 결과값: " + result2);
} catch (ArithmeticException arithmeticException) {
// 예외처리 코드구현 ==> 사용자에게 친절하게 예외 메세지를 알려주는 것이다.
// 아무 예외클래스가 아닌 적합한 예외클래스 지정. 다형성 가능
// 다형성 : RuntimeException , Exception ,... (권장안함)
System.out.println("ArithmeticException: 0 으로 나누어 예외가 발생됨."
+ arithmeticException.getMessage());
// ArithmeticException: 0 으로 나누어 예외가 발생됨./ by zero
arithmeticException.printStackTrace(); // 개발자가 디버깅시 주로 사용됨.
/*
* java.lang.ArithmeticException: / by zero
at exam20_exception.ExceptionTest02_try_catch2_예외메세지제공.main
(ExceptionTest02_try_catch2_예외메세지제공.java:16)
*/
}
System.out.println("----- 프로그램 종료 -----");
}
}
package exam20_exception;
public class ExceptionTest02_try_catch3_다중catch문 {
public static void main(String[] args) {
System.out.println("----- 프로그램 시작 -----");
try {
// 1. ArithmeticException 발생 가능한 코드
int n = 2;
int result = 10/n;
System.out.println("결과값: " + result);
// 2. NullPointerException 발생 가능한 코드
String name = null;
System.out.println("이름 길이: " + name.length());
// 다중 catch 문은 계층구조의 자식부터 처리한다 예를들어 catch 문 처음으로 Exception 이나
// RuntimeException 을 쓰게되면 자식 예외처리는 사용하지 못한다.
} catch (ArithmeticException e) {
System.out.println("0 으로 나누어 예외가 발생됨." + e.getMessage());
} catch (NullPointerException e) {
System.out.println("name 값이 초기화 안되어 있음." + e.getMessage());
} catch (Exception e) { // 가장 마지막 catch 문에 Exception 을 지정하는 방법이 관례.
System.out.println("예외발생." + e.getMessage());
}
System.out.println("----- 프로그램 종료 -----"); // 정상종료
}
}
package exam20_exception;
public class ExceptionTest02_try_catch4_finally문 {
public static void main(String[] args) {
System.out.println("----- 프로그램 시작 -----");
try {
// 1. ArithmeticException 발생 가능한 코드
int n = 2;
int result = 10/n;
System.out.println("결과값: " + result);
// 2. NullPointerException 발생 가능한 코드
String name = null;
System.out.println("이름 길이: " + name.length());
// 다중 catch 문은 계층구조의 자식부터 처리한다 예를들어 catch 문 처음으로 Exception 이나
// RuntimeException 을 쓰게되면 자식 예외처리는 사용하지 못한다.
} catch (ArithmeticException e) {
System.out.println("0 으로 나누어 예외가 발생됨." + e.getMessage());
} catch (NullPointerException e) {
System.out.println("name 값이 초기화 안되어 있음." + e.getMessage());
} catch (Exception e) { // 가장 마지막 catch 문에 Exception 을 지정하는 방법이 관례.
System.out.println("예외발생." + e.getMessage());
} finally {
// 예외가 발생되거나 안되거나 반드시 실행해야되는 문장처리
// 일반적으로 파일사용 및 DB 연동시 close 작업처리
System.out.println("finally문: 반드시 수행되는 문장");
}
System.out.println("----- 프로그램 종료 -----"); // 정상종료
}
}
package exam20_exception;
public class ExceptionTest02_try_catch4_finally문2 {
public static void main(String[] args) {
System.out.println("----- 프로그램 시작 -----");
try {
System.out.println("실행문");
// 예외처리 목적이 아닌 반드시 수행해야되는 문장의 정보를 알려주는 목적
} finally {
// 예외가 발생되거나 안되거나 반드시 실행해야되는 문장처리
// 일반적으로 파일사용 및 DB 연동시 close 작업처리
System.out.println("finally문: 반드시 수행되는 문장");
}
System.out.println("----- 프로그램 종료 -----"); // 정상종료
}
}
다. 예외클래스 + throws 예외클래스 문 ( 위임처리. ************* )
- 예외가 발생된 곳이 아닌 다른 곳에서 위임 받아서 처리하는 방법이다.
- 위임처리방법
main(){ a(){ b(){
//예외가 발생된 곳에서 예외처리
try{
a(); b(); int n= 10/0; //ArithmeticException 발생
}catch(ArithmeticException e){
}
sysout("정상종료");
} } }
##########################################################
main(){ a()throws Arithmet~{ b()throws ArithmeticException{
//예외가 발생된 곳에서 예외처리가 아닌 위임방식
==> 메서드를 호출한 곳으로 위임한다.
try{
a(); b(); int n= 10/0; //ArithmeticException 발생
}catch(Ar~ e){
e.printStackTrace();
}
sysout("정상종료");
} } }
package exam20_exception;
class Test {
public void a() throws ArithmeticException {
b();
};
public void b() throws ArithmeticException {
int n = 0;
int result = 10 / n;
System.out.println("결과값: " + result);
};
}// end Test
public class ExceptionTest03_throws {
public static void main(String[] args) {
System.out.println("----- 프로그램 시작 -----");
Test t = new Test();
try {
t.a();
} catch (ArithmeticException arithmeticException) {
// 정확한 예외클래스를 지정. 다형성 적용가능(권장안함)
// 다형성: RuntimeException, Exception,...
System.out.println(arithmeticException.getMessage());
}
System.out.println("----- 프로그램 종료 -----");
}
}
package exam20_exception;
class Test2 {
public void a() throws ArithmeticException, NullPointerException {
b();
};
public void b() throws ArithmeticException, NullPointerException {
// b 에서 발생할수 있는 모든 예외처리(ArithmeticException, NullPointerException)를 해줘야한다
// 1. ArithmeticException 발생 가능한 코드
int n = 2;
int result = 10/n;
System.out.println("결과값: " + result);
// 2. NullPointerException 발생 가능한 코드
String name = null;
System.out.println("이름 길이: " + name.length());
};
}// end Test
public class ExceptionTest03_throws2_다중throws {
public static void main(String[] args) {
System.out.println("----- 프로그램 시작 -----");
Test2 t = new Test2();
try {
t.a();
} catch (ArithmeticException arithmeticException) {
// 정확한 예외클래스를 지정. 다형성 적용가능(권장안함)
// 다형성: RuntimeException, Exception,...
System.out.println(arithmeticException.getMessage());
} catch (NullPointerException nullPointerException) {
// 정확한 예외클래스를 지정. 다형성 적용가능(권장안함)
// 다형성: RuntimeException, Exception,...
System.out.println(nullPointerException.getMessage());
} catch (Exception exception) { // 마지막 catch 는 Exception 으로 처리한다. (관례)
System.out.println(exception.getMessage());
}
System.out.println("----- 프로그램 종료 -----");
}
}
4) Overriding 관련 throws 처리
부모:
public void a( ) throws ArithmeticException{ }
자식:
@Override
public void a( 같거나 확대 ) ( 축소 ) { } // 가능
@Override
public void a( 같거나 확대 ) throws ArithmeticException ( 축소 ) { } // 가능
@Override
public void a( 같거나 확대 ) throws RuntimeException ( 축소 ) { } // 불가능
@Override
public void a( 같거나 확대 ) throws Exception ( 축소 ) { } // 불가능
@Override
public void a( 같거나 확대 ) throws IOEException ( 축소 ) { } // 불가능
package exam20_exception;
import java.io.IOException;
class Super {
public void a() throws ArithmeticException {}
public void b() throws Exception {}
}
class Child extends Super {
@Override
public void b() throws IOException {} // 부모의 예외클래스보다 하위 클래스는 사용 가능
// @Override
// public void a(){} // 가능
// @Override
// public void a() throws ArithmeticException {} // 가능
@Override
public void a() throws RuntimeException {} // 가능
// @Override
// public void a() throws Exception {} // 부모의 예외클래스보다 상위클래스는 불가능
// @Override
// public void a() throws IOException {} // 부모의 예외클래스보다 상위클래스는 불가능 (확대개념)
}
public class ExceptionTest03_throws3_오버라이딩 {
public static void main(String[] args) {
System.out.println("----- 프로그램 시작 -----");
System.out.println("----- 프로그램 종료 -----");
}
}
2. Runtime 계열의 특징
- try~catch 또는 throws 방식으로 예외처리를 하는 것이 아니다.
이유는 실제로는 실행할 때 예외가 발생되면 안되는 코드들이다.
- 다음 런타임계열은 조건문으로 처리해야 된다.
ArithmeticException( ex) 10/0 )
ex)
int n = 0;
if( n != 0)
int result = 10 / n;
ClassCastException (ex) 클래스 형변환시)
ex)
Employee e = new Manager( );
Manager m = (Manager)e;
Cat c = (Cat)e; // ClassCastException 발생
>>>
Employee e = new Manager( );
Manager m = (Manager)e;
if( e instanceof Cat )
Cat c = (Cat)e;
NullPointerException
(ex) null 값을 가진상태로 메서드 호출시
ex)
String name = null;
sysout( name.length( ) ); // NullPointerException 발생
>>>
String name = null;
if( name != null )
sysout( name.length( ) );
ArrayIndexOutOfBoundsException
(ex) 없는 배열요소 접근시
3. 비 런타임 계열
- IOException, SQLException
- 규칙: 반드시 try~catch 또는 throws 문을 이용해서 예외처리해야 된다. ( * )
예외처리 안하면 컴파일 예외가 발생된다.
결론은 I/O 작업 또는 DB 연동작업시 무조건 예외처리를 해야 된다. ( * )
4. 명시적으로 예외를 발생시킬 수 있다. + 사용자정의 예외 클래스 작성
- 용도: 시스템은 실행문장을 예외로 처리하지 않는 정상적인 코드로
인식하기 때문이다. 그런데 사용자는 문제있는코드로 인식 할수 있다.
ex) Random 클래스에서 랜던값이 0 일때
- 문법:
ex)
if( n == 0) throw new MyException("예외메시지"); // 강제적(명시적)으로 예외발생
- throw vs throws
throw: 명시적으로 에외 발생할 때
throws: 위임할때
- 사용자정의 예외 클래스 작성 방법:
public class MyException extends Exception {
// 문자열 하나 저장가능한 생성자만 있으면 됨.
// 필요시 추가로 변수, 메서드 지정 가능.
public MyException(String message) {
super(message);
}
}
package exam20_exception;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class ExceptionTest04_비런타임계열처리 {
public static void main(String[] args) {
File f = new File("C:\\java_study\\eclipse\\workspace\\HelloTest\\src\\exam20_exception\\ExceptionTest04_비런타임계열처리.java");
// 입 출력을 할때 무조건 예외처리를 해야한다.
try {
FileReader fileReader = new FileReader(f);
BufferedReader bufferedReader = new BufferedReader(fileReader);
String s = bufferedReader.readLine(); // 한줄 읽기
while ( s != null) {
System.out.println(s);
s = bufferedReader.readLine(); // 한줄 읽기
}
} catch (FileNotFoundException e) { // -> new BufferedReader(fileReader); 예외처리
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) { // -> bufferedReader.readLine(); 예외처리
// TODO Auto-generated catch block
e.printStackTrace();
}
}// end main
}
* 명시적으로 예외발생
package exam20_exception;
import java.util.Random;
//ArithmeticException: 0으로 나눴을때 발생하는 예외
// 사용자 클래스
class MyRandom {
public int random() throws MyException { // throws: 위임할때 사용
Random r = new Random();
int n = r.nextInt(3); // 0, 1, 2
// 조건문 추가 + throw
// throw: 명시적으로 예외를 발생시키고 싶을때 사용
// if(n == 0) throw new ArithmeticException("0 이 랜덤값 반환되어 예외발생");
// 현재 이상황에서 적합하지 않은 예외클래스이다.(ArithmeticException)
// 그래서 직접 '사용자정의 에외 클래스' 를 만들어줘야한다.
// >>>
if(n == 0) throw new MyException("0 이 랜덤값 반환되어 예외발생");
return n;
}
}// end class
public class ExceptionTest05_명시적예외발생 {
public static void main(String[] args) {
System.out.println("----- 프로그램 시작 -----");
MyRandom r = new MyRandom();
try {
// 0 이 나오면 명시적으로 예외를 발생시키고 싶다. ( 시스템상으로는 예외x )
// 명시적으로 예외를 발생시켰어도 예외처리를 해줘야 한다.
int result = r.random();
System.out.println("랜덤값: " + result);
} catch (MyException e) {
// TODO: handle exception
System.out.println(e.getMessage());
}
System.out.println("----- 프로그램 종료 -----");
}// end main
}
package exam20_exception;
// 사용자 정의 예외 클래스 작성 방법
public class MyException extends Exception {
public MyException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
}
'Programming > JAVA(eclipse)' 카테고리의 다른 글
java 13 일차 _ 12일차 정리 (0) | 2024.03.26 |
---|---|
java 12일차_ 02. 제네릭스( generics ) (0) | 2024.03.25 |
java 11일차 _ 01. 유틸리티 클래스( Arrays ) (0) | 2024.03.22 |
java 11일차 _ 01. 유틸리티 클래스( enum ) (0) | 2024.03.22 |
java 11일차 _ 01. 유틸리티 클래스( 날짜 데이터 StringTokenizer ) (0) | 2024.03.22 |