지구정복
[JAVA] 11/19 | 예외처리(다중catch, 예외강제발생, 예외떠넘기기, 사용자정의예외), 열거타입 본문
[JAVA] 11/19 | 예외처리(다중catch, 예외강제발생, 예외떠넘기기, 사용자정의예외), 열거타입
nooh._.jl 2020. 11. 19. 12:56복습
OOP이론 (아래는 OOP이론을 구성하는 것들)
캡슐
상속
추상
다형
형변환
오버라이드
추상클래스
인터페이스 - 구현클래스의 메서드를 사용
추상메서드
중첩클래스
멤버필드
인스턴스 멤버 클래스
스태틱(정적)멤버 클래스
로컬 클래스
익명 클래스
에러처리
에러
컴파일 에러
실행 에러(런타임 에러)
값의 오류 (=논리 오류)
IF문으로 검출
예외(Exception)를 통해서 처리
try {
구문
} catch(익셉션 객체변수) {
익셉션 발생시 처리부분
} finally {
무조건 실행부분
}
ㅇ예외처리
-try catch문 사용
num3 를 0으로 나누면 에러가 나지만 try catch문 에러처리로 에러가 안나는 것을 알 수 있다.
finally 구문을 추가하면 에러가 나든지 나지 않든지 fianlly구문을 무조건 실행한다.
public class Ex1119_Exception01 {
public static void main(String[] args) {
System.out.println("시작");
System.out.println("1");
int num1 = 2;
int num2 = 0;
int num3 = 10;
try {
System.out.println("2");
//int result = num3/num1;
int result = num3/num2;
System.out.println("3");
System.out.println("결과: "+ result);
} catch(ArithmeticException e) {
System.out.println("4");
} finally {
System.out.println("5");
}
System.out.println("끝");
}
}
-다중 catch 사용하기
try블록 내부는 다양한 종류의 예외가 발생할 수 있다. 이를 해결하는 방법이 여러 개의 catch문을 사용하는 것이다.
하지만 catch블록이 여러 개라 할지라도 단 하나의 catch 블록만 실행된다.
그 이유는 try 블록에서 동시 다발적으로 예외가 발생하지 않고, 하나의 예외가 발생하면 즉시 실행을 멈추고 해당 catch
블록으로 이동하기 때문이다.
public class Ex1119_Exception02 {
public static void main(String[] args) {
try {
String data1 = args[0];
String data2 = args[1];
int v1 = Integer.parseInt(data1);
int v2 = Integer.parseInt(data2);
int result = v1 + v2;
System.out.println(data1 + "+" + data2 + "=" + result);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("실행 매개값의 수가 부족합니다.");
System.out.println("[실행방법]");
System.out.println("java 클래스명 num1 num2");
} catch (NumberFormatException e) {
System.out.println("숫자로 변환할 수 없습니다.");
} finally {
System.out.println("다시 실행하세요.");
}
}
}
그렇기 때문에 상위 예외 클래스가 하위 예외 클래스보다 아래쪽에 위치해야 한다.
try블록에서 예외가 발생했을 때, 예외를 처리해줄 catch블록은 위에서부터 차례대로 검색된다.
만약 상위 예외 클래스의 catch블록이 위에 있다면, 하위 예외 클래스의 catch 블록은 실행되지 않는다.
왜냐하면 하위 예외는 상위 예외를 상속했기 때문에 상위 예외 타입도 되기 때문이다.
아래 코드처럼 상위 예외 클래스인 Exception이 ArrayIndexOutOfBoundsException보다 위에 있으면 에러가 난다.
public class Ex1119_Exception03 {
public static void main(String[] args) {
try {
String data1 = args[0];
String data2 = args[1];
int v1 = Integer.parseInt(data1);
int v2 = Integer.parseInt(data2);
int result = v1 + v2;
System.out.println(data1 + "+" + data2 + "=" + result);
} catch (Exception e) {
System.out.println("실행에 문제가 있습니다.");
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("실행 매개값의 수가 부족합니다.");
System.out.println("[실행방법]");
System.out.println("java 클래스명 num1 num2");
} finally {
System.out.println("다시 실행하세요.");
}
}
}
따라서 아래처럼 상위 에러 클래스인 Exception이 아래에 위치해야 한다.
public class Ex1119_Exception03 {
public static void main(String[] args) {
try {
String data1 = args[0];
String data2 = args[1];
int v1 = Integer.parseInt(data1);
int v2 = Integer.parseInt(data2);
int result = v1 + v2;
System.out.println(data1 + "+" + data2 + "=" + result);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("실행 매개값의 수가 부족합니다.");
System.out.println("[실행방법]");
System.out.println("java 클래스명 num1 num2");
} catch (Exception e) {
System.out.println("실행에 문제가 있습니다.");
} finally {
System.out.println("다시 실행하세요.");
}
}
}
-멀티 catch
하나의 catch 블록에서 여러 개의 예외를 처리할 수 있다.
catch 블록의 괄호 안에 예외를 | 로 연결하면 된다.
-예외 강제로 발생시키기
보통 메소드안에서 강제로 익셉션을 발생시킬 때 사용한다.
public class Ex1119_Exception04 {
//인스턴스 메소드
public void method1(int n) {
System.out.println("시작");
int n1 = 10;
try {
if(n1<100) {
//강제 익셉션 발생
throw new Exception("익셉션 발생");
}
} catch(Exception e) {
System.out.println("[익셉션]"+e.getMessage());
}
System.out.println("끝");
}
public static void main(String[] args) {
Ex1119_Exception04 e = new Ex1119_Exception04();
e.method1(10); //정상
e.method1(101); //비정상
}
}
-예외 떠넘기기
메소드 내부에서 예외가 발생할 수 있는 코드를 작성할 때 try-catch 블록으로 예외를 처리하는 것이 기본이지만,
경우에 따라서는 메소드를 호출한 곳으로 예외를 위임시킬 수 있다. 이때 사용하는 키워드가 throws이다.
throws 키워드는 메소드 선언부 끝에 작성되어 메소드에서 처리하지 않은 예외를 호출한 곳으로 떠넘기는 역할을 한다.
throws 키워드 뒤에는 떠넘길 예외 클래스를 쉼표로 구분해서 나열해주면 된다.
각각의 에러를 나열해도 되지만 아래처럼 모든 예외를 위임시킬 수 있다.
리턴타입 메소드명(매개변수1, ...) throws Exception { }
throws 키워드가 붙어있는 메소드는 반드시 try 블록 내에서 호출되어야 한다. 그리고 catch 블록에서 위임받은 예외를
처리해야 한다.
public class Ex1119_Exception04 {
//인스턴스 메소드
public void method1(int n) {
System.out.println("시작");
int n1 = 10;
try {
if(n1<100) {
//강제 익셉션 발생
throw new Exception("익셉션 발생");
}
} catch(Exception e) {
System.out.println("[익셉션]"+e.getMessage());
}
System.out.println("끝");
}
//예외 위임시키는 method2
public void method2(int n) throws Exception {
System.out.println("시작");
int n1 = 10;
if(n1<100) {
throw new Exception("익셉션 발생");
}
System.out.println("끝");
}
public static void main(String[] args) {
Ex1119_Exception04 e = new Ex1119_Exception04();
e.method1(10);
e.method1(101);
//예외를 위임받았으므로 try-catch 블럭으로 묶어준다.
try {
e.method2(101);
} catch(Exception e1) {
System.out.println("[익셉션] : "+e1.getMessage());
}
}
}
main() 메소드에서도 throws 키워드를 사용해서 예외를 넘길 수 있는데 결국 JVM이 최종적으로 예외 처리를 하게 된다.
하지만 이는 좋은 방법이 아니다.
-ProcessBuilder로 예외 위임 확인하기
아래 코드를 실행하면 인터넷창이 열린다.
이때 java.io.IOException을 추가하지 않으면 IOException이 발생한다.
import java.io.IOException;
public class Ex1119_ProcessBuilder01 {
public static void main(String[] args) {
try {
ProcessBuilder pb =
new ProcessBuilder("C:\\Program Files\\Internet Explorer\\iexplore");
pb.start();
} catch(IOException e) {
System.out.println("[예외] : "+e.getMessage());
}
}
}
위의 예제를 이클립스에서 try-catch블럭을 만들어보자. 먼저 아래처럼 오류가 나면 에러가 나는 구문을 드래그한다.
자동적으로 try-catch블럭이 생긴다.
-사용자 정의 예외와 예외 발생
프로그램을 개발하다 보면 자바 표준 API에서 제공하는 예외 클래스만으로는 다양한 종류의 예외를 표현할 수가 없다.
이럴 경우 개발자가 직접 예외를 정의해서 만들어야 한다. 이를 사용자 정의 예외라고 한다.
사용자 정의 예외 클래스는 컴파일러가 체크하는 일반 예외로 선언할 수도 있고,
컴파일러가 체크하지 않는 실행 예외로 선언할 수도 있다.
일반 예외로 선언할 경우 Exception을 상속하면 되고,
실행 예외로 선언할 경우 RuntimeException을 상속하면 된다.
아래 예시를 확인하자.
//사용자 정의 예외 클래스 선언
class BalanceInsufficientException extends Exception {
public BalanceInsufficientException() { }
public BalanceInsufficientException(String message) {
super(message);
}
}
class Account {
private long balance;
public Account() { }
//통장잔고확인 메소드
public long getBalance() {
return balance;
}
//예금하기 메소드
public void deposit(int money) {
balance += money;
}
//출금하기 메소드 - 사용자 정의 예외 위임하기
public void withdraw(int money) throws BalanceInsufficientException {
if(balance < money) {
throw new BalanceInsufficientException("잔고부족: "+(money-balance)+"가 모자람");
}
balance -= money;
}
}
public class Ex1119_AccountExample {
public static void main(String[] args) {
Account account = new Account();
//예금하기
account.deposit(10000);
System.out.println("예금액: "+account.getBalance());
//출금하기
try {
account.withdraw(30000);
} catch(BalanceInsufficientException e) {
String message = e.getMessage();
System.out.println(message);
System.out.println();
e.printStackTrace(); //예외 추적후 출력
}
}
}
위의 예제를 이클립스에서 빠르게 만들어보자.
먼저 사용자정의 예제인 BalanceInsufficientException 클래스를 만드는데 아래처럼 만든다.
그러면 아래처럼 자동적으로 생성자들이 만들어진다.
ㅇ열거타입
열거타입은 한정된 값만을 갖는 데이터 타입이 열거타입이다. 열거 타입은 몇 개의 열거 상수 중에서 하나의 상수를 저장하는 데이터 타입이다.
열거 타입의 예로는 요일에 대한 데이터다.
요일은 월 화 수 목 금 토 일이라는 일곱 개의 값만을 갖고, 계절에 대한 데이터는 봄 여름 가을 겨울이라는 네 개의 값만을 가진다.
열거타입 이름은 관례적으로 첫 문자를 대문자로 하고 나머지는 소문자로 구성한다.
또한 열거타입의 데이터들은 대문자를 사용한다.
아래는 열거타입을 선언한 예이다. 클래스 선언과 비슷하다.
public enum Week {
//열거상수
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY
}
열거타입 사용은 아래와 같다.
열거타입 변수이름 = 열거타입.열거상수;
Week today = Week.SUNDAY;
더해서 열거객체의 메소드도 확인하자.
package com;
public class EnumWeekExample02 {
public static void main(String[] args) {
Week w1 = Week.SATURDAY;
Week w2 = Week.SATURDAY;
System.out.println(w1 == w2);
////열거객체의 메소드
//String
System.out.println(w1.name());
//Week
System.out.println(Week.SATURDAY);
//열거상수 첫 번째가 0부터 시작
System.out.println(w1.ordinal());
//열거객체들을 배열로 만들기
Week[] days = Week.values();
for(Week day : days) {
System.out.println(day);
}
}
}
Calendat를 이용해서 오늘의 요일을 얻고나서 열거타입변수 today에 해당 열거 상수를 대입하는 예제를 살펴보자.
package com;
import java.util.Calendar;
public class EnumWeekExample {
public static void main(String[] args) {
//열거타입 변수 선언
Week today = null;
Calendar c = Calendar.getInstance();
//일(1) ~ 토(7) 까지의 숫자리턴
int week = c.get(Calendar.DAY_OF_WEEK);
switch(week) {
case 1:
today = Week.SUNDAY; break;
case 2:
today = Week.MONDAY; break;
case 3:
today = Week.TUESDAY; break;
case 4:
today = Week.WEDESDAY; break;
case 5:
today = Week.THURSDAY; break;
case 6:
today = Week.FRIDAY; break;
case 7:
today = Week.SATURDAY; break;
}
System.out.println("오늘 요일: "+today);
if(today == Week.SUNDAY) {
System.out.println("일요일에는 축구를 합니다.");
} else {
System.out.println("열심히 자바 공부를 합니다.");
}
}
}
복습
복습진도
chapter1 ~ 10
확인문제에 답하기
1.자료
기본 자료형
변수와 타입
연산자
객체 자료형
2. 제어
조건문과 반목문
3. 객체자료형
참조타입
클래스
상속
인터페이스
중첩클래스
예외