OOP(5) : 예외 처리 / try-catch, throw, finally
객체 지향 프로그래밍(OOP: Object-Oriented Programming)
1. 데이터 보호
패키지 / 접근제어자 / 캡슐화
2. 재사용
변경해서 사용(상속 : is-a) / 그대로 사용(포함 : has-a)
3. 다형성
오버라이딩 / 오버로딩
4. 형변환
5. 추상 클래스 / 인터페이스
+5 내부 클래스
6. 예외처리 ← 오늘은 여기!
예외처리
프로그램을 실행할 때 발생할 수 있는 에러에 미리 대비하는 코드이다.
비정상적인 종료를 방지하고 정상상태를 유지하기 위해 사용한다.
*** 예외처리를 한다고 에러를 잡아주는 게 아니다. 에러를 건너뛰는 것이다. ***
에러 = 프로그래머의 실수 or 사용자의 입력
예외처리해 주어야 하는 유형은 크게 다음과 같다. (당연히 더있음)
파일 입출력, 읽기 → IOException
데이터베이스 연결 → SQLException
네트워크 → MalformedURLException
크롤링 등을 포함한 위 3가지는 컴파일 시에 예외처리 여부를 확인한다.
java파일(원시 소스)은 프로그래머만 인식하고 class파일(바이트 코드)은 컴퓨터가 인식한다.
자바 컴파일러가 자바 소스코드를 바이트코드로 만들고, 인터프리터가 바이트코드를 해석하고 실행한다.
이 때 컴파일 단계에서 발생하는 에러를 컴파일 에러라고 하고, 해석 단계에서 발생하는 에러를 런타임 에러라고 한다.
컴파일 에러는 반드시 예외처리를 해야 하고, 런타임 에러는 필요한 경우에만 에외처리를 해도 된다.
에러 : 심각한 에러(소스상에서 변경할 수 없는 에러)
→ 예: 메모리가 부족하여 강제 종료됨
예외 : 가벼운 에러(소스상에서 수정이 가능한 에러)
→ 예: 사이트 연결(주소가 다르다), 파일 읽기 시 경로가 다르다, 서버 연결 시 IP가 다르다 등
예외처리를 위한 클래스 구조
예외처리에도 순서가 있고 그 순서를 잘 지켜야 한다.
더 상위의 예외를 먼저 처리한 후에 그 하위의 예외를 처리하면 에러가 난다.
이미 더 넓은 범위에서 커버친 부분인데 또 처리하는 셈이니까...
자주 등장하는 예외
CheckException (반드시 예외처리가 필요함)
- ***IOException : 파일 입/출력
- ***SQLException :DB 연결시
- MalformedURLException : 네트워크 연결시
- ClassNotFoundException : 메모리 할당 시, new가 없을 때
- InterrupedException : 스레드와 관련됨. 충돌 방지
⇢ 이 모든걸 뭉뚱그려서 그냥 Exception 으로 처리하면 편하다.
UnCheckException (필요시에만 예외처리, 생략 가능)
- ArrayIndexOutOfBoundsException : 배열 범위를 벗어났을 때
- NumberFormatException : 정수 변환이 안 된 경우
- ArithmeticException : 0으로 나눈 경우
- ClassCastException : class형 변환을 잘못한 경우
- NullPointerException : 주소 값이 없는 경우
예외처리 방법
1. 예외 복구 : try~catch문
try해보고 예외가 발생하면 그 예외를 catch해놓고 나머지를 수행한다는 느낌.
catch문은 여러 번 사용이 가능하다. 여러 가지 예외를 하나하나 지정해서 catch문을 작성할 수 있다.
try에서 에러가 없는 경우에는 catch블록 내에 있는 코드는 수행하지 않고 finally로 빠져나간다.
finally 는 데이터베이스, 네트워크, 파일 읽기, 크롤링시 프로그램을 종료하는 데에 주로 사용된다.
try {
//정상으로 수행하는 문장
} catch (Exception ex) {
/*에러 처리/복구하는 문장*/ } finally { //생략가능, 필요시에만 사용
//반드시 수행하는 문장 : 오라클/서버/파일 등을 닫는 등..
}
package day24;
public class Ex2 {
public static void main(String[] args) {
try {
// int[] arr = {1};
// arr[1] = 20; //ArrayIndexOutOfBoundsException
// System.out.println(10 / 0); //ArithmeticException
// String a = " 10";
// System.out.println(Integer.parseInt(a)); //NumberFormatException
Class.forName("day24.Ex11"); //ClassNotFoundException
} catch (ArrayIndexOutOfBoundsException ex) {
System.out.println("배열 범위를 초과함.");
} catch (ArithmeticException ex) {
System.out.println("0으로 나눌 수 없음.");
} catch (NumberFormatException ex) {
System.out.println("정수형 변환이 안 되었음.");
} catch (ClassCastException ex) {
System.out.println("클래스 형변환 문제 발생함.");
} catch (NullPointerException ex) {
System.out.println("클래스 객체의 값이 없음.");
} catch (Exception ex) {
//예외처리중에 가장 큰 클래스. 맨 위로 올라가면 에러난다.
//이미 Exception이 모두 잡을 수 있기 때문에..
System.out.println("(뭔진몰라도 아무튼)예외 에러 발생함.");
} catch (Throwable ex) {
//얘가 Exception보다 더 크다.
//예외처리+에러까지 잡아주는 ...
System.out.println("던져~던져!");
}
System.out.println("PROGRAM CLOSED");
}
}
언제나 try-catch문이 가장 바깥쪽에서 감싸줄 필요는 없다.
예외가 발생할 법한 부분만 감싸줘도 충분하다.
public class MainClass {
public static void main(String[] args) {
try {
for(int i=1; i<=10; i++) {
int j = (int)(Math.random()*3);
System.out.println("i="+i+",i/j="+i/j);
}
}catch(Exception ex) {
//에러가 발생하기만 하면 for문 자체가 멈춘다.
System.out.println("Error");
}
for(int i=1; i<=10; i++) {
try {
int j = (int)(Math.random()*3);
System.out.println("i="+i+",i/j="+i/j);
}catch(Exception ex) {
//에러가 발생해도 for문은 정해진 횟수만큼 돌아간다.
System.out.println("Error");
}
}
}
}
2. 예외 발생시키기 : throw (throws와 다름)
throw를 사용해서 고의로 예외를 발생시킬 수 있다.
프로그램의 안정성을 테스트하기 위해 주로 사용하고, 임의로 발생한다.
//연산자 new를 이용해서 발생시키려는 예외 클래스의 객체를 만듬
Exception e = new Exception("thorw example");
//String을 넣어주면 getMessage()를 통해 해당 메시지를 얻을 수 있다.
//throw로 예외를 발생시킴
throw e;
public static void main(String[] args) {
try {
Exception e = new Exception("throw Exception");
throw e;
//throw new Exception("throw Exception"); 이렇게 짧게도 쓸 수 있음.
} catch (Exception e) {
System.out.println("Error:" + e.getMessage());
}
}
3. 예외 회피 : throws
throws를 이용하면 예외 처리를 위한 예외를 메서드에 선언할 수 있다.
try-catch문과 달리 메서드의 선언부에 키워드 throws와 함께 발생할 수 있는 예외를 적어 준다.
또한 try-catch와 달리 예외의 클래스 구조와 관계없이 순서 무관하게 작성이 가능하다.
(상위 Exception을 하위 Exception 보다 먼저 명시한다던가)
void method() throws Exception1, Exception2,...ExceptionN{
//메서드 내용
}
임의의 사용자가 이 메서드를 사용하기 위해 어떤 예외들이 처리되어야 하는지 쉽게 알 수 있다.
예외를 메서드에 명시하는 것은 해당 예외를 처리하는 것이 아니라,
예외가 발생할 가능성이 있는 메서드를 호출한 메서드에게 예외를 전달하여 예외처리를 떠맡기는 것이다.
예외 임의 발생
자바에서 모든 에러에 대한 처리를 할 수는 없기 때문에,
사용자 정의 예외 처리도 가능하다. → class MyException extends Exception
자세한 내용은 https://www.geeksforgeeks.org/user-defined-custom-exception-in-java/ 참조
+멀티블록
OR을 써서 여러 개의 예외를 같이 잡을 수 있다.
package day24;
public class Ex3 {
public static void main(String[] args) {
try {
// System.out.println(10/0);
int[] a = {1};
a[1] = 0;
//멀티블록. 하나로 여러 개의 에러를 잡는것임. OR로 연결가능함.
}catch(ArrayIndexOutOfBoundsException | ArithmeticException ex) {
System.out.println("Error!!");
}
}
}
getMessage()와 printStackTrace()
getMessage()를 통해 어떤 에러가 발생했는지 정보를 출력하거나,
printStackTrace()로 어느 위치에서 에러가 발생했는지 확인이 가능하다.
보통 catch문에 써 준다.
package day24;
/*
* 에러메시지 처리방법
* = getMessage() -> 실제 에러내용만 출력
* = printStackTrace() -> 에러 위치 확인***
*/
import java.util.*;
public class Ex3_1 {
public static void main(String[] args) {
try {
Scanner scan = new Scanner(System.in);
System.out.print("first int:");
int num1 = scan.nextInt();
System.out.print("second int:");
int num2 = scan.nextInt();
int[] arr = new int[2];
arr[0] = num1;
arr[1] = num2;
int result = num1/num2;
System.out.println(result);
}catch(Exception ex) {
System.out.println(ex.getMessage());
ex.printStackTrace();
}
}
}
'부트캠프(END) > Java' 카테고리의 다른 글
java.lang package (0) | 2022.06.08 |
---|---|
OOP(4) : 내부 클래스 (0) | 2022.06.03 |
OOP(3) : 형변환, 추상 클래스, 인터페이스 (0) | 2022.06.02 |