Ⅰ. Exception
-- Package(my.day15.a.exception), Class (ExceptionTest1(main method 포함))
1. ArrayIndexOutOfBoundsException
-- 배열의 크기가 오버가 되어지면 발생하는 Exception
public static void main(String[] args) {
// 1. ArrayIndexOutOfBoundsException
// 배열의 크기가 오버가 되어지면 발생하는 Exception
String[] subjectArr = {"자바", "오라클", "JSP"};
for(int i=0; i<=subjectArr.length; i++) {
System.out.println(subjectArr[i]);
}
}
public static void main(String[] args) {
// 1. ArrayIndexOutOfBoundsException
// 배열의 크기가 오버가 되어지면 발생하는 Exception
String[] subjectArr = { "자바", "오라클", "JSP" };
try {
for (int i = 0; i <= subjectArr.length; i++) {
System.out.println(subjectArr[i]);
}
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println(">> 배열의 인덱스 범위가 초과되었습니다.");
System.out.println("----------------------------");
e.printStackTrace();
}
}
e.printStachTrace() : 에러 메시지 외에 어디가 잘못 되었는지 추적해 준다.
catch (ArrayIndexOutOfBoundsException e) {
System.out.println(e.getMessage());
}
▷결과
3
-- 에러 메시지만 보여 준다
2. ArithmeticException
-- 어떤 수를 0으로 나눌 때 발생되어지는 Exception 즉, 분모를 0으로 할 때 발생되어지는 Exception
for(int i=0; i<=5; i++) { // i는 0~5까지
int result = 50/(3-i);
System.out.println("result => 50/"+(3-i)+"="+result);
}
try {
for (int i = 0; i <= 5; i++) { // i는 0~5까지
int result = 50 / (3 - i);
System.out.println("result => 50/" + (3 - i) + "=" + result);
}
} catch (ArithmeticException e) {
System.out.println(">> 분모는 0으로 할 수 없습니다.");
}
▷결과
result => 50/3=16
result => 50/2=25
result => 50/1=50
>> 분모는 0으로 할 수 없습니다.
for (int i = 0; i <= 5; i++) { // i는 0~5까지
int result = 50 / (3 - i);
System.out.println("result => 50/" + (3 - i) + "=" + result);
}
System.out.println(">> 프로그램 종료합니다. <<");
-- 이 때, 위에서 오류가 발생하면서 ">> 프로그램 종료합니다. <<" 문장은 출력되지 않는다.
try {
for (int i = 0; i <= 5; i++) { // i는 0~5까지
int result = 50 / (3 - i);
System.out.println("result => 50/" + (3 - i) + "=" + result);
}
}finally {
System.out.println(">> 프로그램 종료합니다. <<"); // try finally를 사용하지 않으면 윗 줄에서 오류가 발생하면서 출력되지 않는다.
}
-- 오류가 발생해든 발생하지 않든 문장을 출력하고 싶을 때 try finally를 사용한다.
-- try{ } 부분의 실행에 있어서 예외(exception)가 발생하든지 발생하지 않든지 관계없이 try{ } 부분의 실행이 끝나고 나서 무조건 실행되어지는 부분이 finally{ } 이다.
-- 오류가 발생하기 때문에 아래에 다른 코드를 추가할 경우 출력되지 않고 멈춘다.
try {
for (int i = 0; i <= 5; i++) { // i는 0~5까지
int result = 50 / (3 - i);
System.out.println("result => 50/" + (3 - i) + "=" + result);
}
} catch (ArithmeticException e) {
System.out.println(">> 분모는 0으로 할 수 없습니다.");
} finally {
System.out.println("-- 예외가 발생하든 발생하지 않든 관계없이 무조건 실행되어야 하는 부분입니다. --");
}
-- try catch와 finally를 같이 쓸 수 있다.
-- catch로 오류를 처리해 주었으므로 아래에 다른 코드를 추가할 경우 계속 진행되어 출력된다.
-- 같은 패지키(my.day15.a.exception)에 Class(ExceptionTest2) 생성한다.
public class ExceptionTest2 {
public static void main(String[] args) {
try {
for (int i = 0; i <= 5; i++) { // i는 0~5까지
int result = 50 / (3 - i);
System.out.println("result => 50/" + (3 - i) + "=" + result);
}
} catch (ArithmeticException e) {
System.out.println(">> 분모는 0으로 할 수 없습니다.");
return; // 메소드를 끝낸다.
} finally {
System.out.println("-- 예외가 발생하든 발생하지 않든 관계없이 무조건 실행되어야 하는 부분입니다. --");
}
System.out.println(">>> 프로그램 종료합니다. Good Bye! <<<");
}
-- catch에 return을 넣고 실행해 보면 ">>> 프로그램 종료합니다. Good Bye! <<<" 코드가 실행되지 않는다.
-- return : 현재 진행중인 메소드가 main() 메소드이므로, main() 메소드를 종료한다.
-- 하지만 finally{ }가 있으면 finally{ } 부분을 실행해준 다음에 main() 메소드를 종료한다.
-- 같은 패지키(my.day15.a.exception)에 Class(ExceptionTest2)를 복사하여 Class(ExceptionTest3) 생성한다.
public class ExceptionTest3 {
public static void main(String[] args) {
try {
for (int i = 0; i <= 5; i++) { // i는 0~5까지
int result = 50 / (3 - i);
System.out.println("result => 50/" + (3 - i) + "=" + result);
}
} catch (ArithmeticException e) {
System.out.println(">> 분모는 0으로 할 수 없습니다.");
System.exit(0);
} finally {
System.out.println("-- 예외가 발생하든 발생하지 않든 관계없이 무조건 실행되어야 하는 부분입니다. --");
}
System.out.println(">>> 프로그램 종료합니다. Good Bye! <<<");
}
}
-- System.exit를 넣고 실행해보면 finally도 출력되지 않는다.
-- System.exit : 프로그램을 종료시키는 것이다.
-- 안에 숫자는 마음대로 쓸 수 있지만 숫자 0의 의미는 개발자가 프로그램을 정상적인 종료를 해 주겠다는 말이고, 0이 아닌 정수(ex. -234, 2568)의 의미는 개발자가 프로그램을 비정상적인 종료로 해주 겠다는 말이다.
public class ExceptionTest4 {
public static void main(String[] args) {
int[] noArr = {10,20,30,40};
for (int i = 0; i < 5; i++) {
try {
int result = noArr[i]/(3-i);
System.out.println("result = "+noArr[i]+"/"+(3-i)+"="+result);
}catch(ArithmeticException e) {
System.out.println(">> 분모는 0으로 할 수 없습니다.");
}catch(ArrayIndexOutOfBoundsException e) {
System.out.println(">> 배열의 인덱스 범위가 초과되었습니다.");
}finally {
System.out.println("-- 오류가 발생하든지 발생하지 않든지 무조건 실행하는 것입니다. --");
}
} // end of for----------------
System.out.println(">>> 프로그램 종료합니다. Good Bye! <<<");
} // end of main()--------------------------------------------------------------
}
public class ExceptionTest5 {
public static void main(String[] args) {
int[] noArr = {10,20,30,40};
for (int i = 0; i < 5; i++) {
try {
int result = noArr[i]/(3-i);
System.out.println("result = "+noArr[i]+"/"+(3-i)+"="+result);
}catch(ArithmeticException | ArrayIndexOutOfBoundsException e) {
System.out.println(">> 분모는 0으로 할 수 없거나 배열의 인덱스 범위가 초과되었습니다."); // JDK 1.7부터 가능
} finally {
System.out.println("-- 오류가 발생하든지 발생하지 않든지 무조건 실행하는 것입니다. --");
}
} // end of for----------------
System.out.println(">>> 프로그램 종료합니다. Good Bye! <<<");
} // end of main()--------------------------------------------------------------
}
-- 위의 코드를 아래 코드처럼 OR로 붙여서 사용할 수 있다. (JDK 1.7부터 가능)
public class ExceptionTest6 {
public static void main(String[] args) {
int[] noArr = {10,20,30,40};
String str = "똘똘이";
for (int i = 0; i < 5; i++) {
try {
int result = noArr[i]/(3-i);
int strNum = Integer.parseInt(str); // NumberFormatExceptionberformat
System.out.println("result = "+noArr[i]+"/"+(3-i)+"="+result);
System.out.println("strNum => "+strNum);
} catch(ArithmeticException | ArrayIndexOutOfBoundsException e) {
System.out.println(">> 분모는 0으로 할 수 없거나 배열의 인덱스 범위가 초과되었습니다.");
} catch(Exception e){ // Exception : 모든 Exception을 다 받아준다
System.out.println(e.getMessage());
} finally {
System.out.println("-- 오류가 발생하든지 발생하지 않든지 무조건 실행하는 것입니다. --");
}
} // end of for----------------
System.out.println(">>> 프로그램 종료합니다. Good Bye! <<<");
} // end of main()--------------------------------------------------------------
}
-- Exception : 모든 Exception을 다 받아준다.
-- 순서를 바꿀 경우 오류가 발생한다.
-- 이미 위에 Exception catch 블록 부분에서 다 처리가 되었기 때문에 아래로 코드가 진행되지 않는다.
-- 그러므로 catch의 코딩 순서는 특정한 일부의 Exception부터 기술하고 아래로 내려가면서 더 많은 Exception을 받을 수 있는 것으로 코딩을 해야 한다.
-- Package(my.day15.b.exception), Class(Sungjuk, MainApp)를 생성
-- get set을 한 뒤 국영수 set을 없애고 하나의 setPoint에서 하도록 한다.
-- Generate Constructor useing Fields
-- 기본 생성자 생성
-- throws : setPoint 메소드는 실행시 NumberFormatException을 유발시킬 수 있으니 setPoint 메소드를 실행하는 쪽에서 NumberFormatException 처리를 하라는 말이다. (try catch)
package my.day15.b.exception;
public class Sungjuk {
private String name;
private int kor;
private int eng;
private int math;
public Sungjuk(){ }
public Sungjuk(String name, int kor, int eng, int math) {
this.name = name;
this.kor = kor;
this.eng = eng;
this.math = math;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getKor() {
return kor;
}
public int getEng() {
return eng;
}
public int getMath() {
return math;
}
public void setPoint(String kor, String eng, String math) throws NumberFormatException {
this.kor = Integer.parseInt(kor);
this.eng = Integer.parseInt(eng);
this.math = Integer.parseInt(math);
}
}
-- Scanner를 받아온다.
public class MainApp {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
Sungjuk[] sjArr = new Sungjuk[3];
System.out.print(">> 학생명 => ");
String name = sc.nextLine();
System.out.print(">> 국어 => ");
String kor = sc.nextLine();
System.out.print(">> 영어 => ");
String eng = sc.nextLine();
System.out.print(">> 수학 => ");
String math = sc.nextLine();
Sungjuk sj = new Sungjuk(); // 기본 생성자
sj.setName(name);
try {
sj.setPoint(kor, eng, math);
}catch(NumberFormatException e) {
System.out.println(">> 과목의 모든 점수는 숫자로만 입력하세요!!");
sj = null;
}
sc.close();
}
}
-- Sungjuk[] sjArr 속에 sj를 저장한다.
if(sj != null) {
for(int i=0; i<sjArr.length; i++) {
if(sjArr[i] == null) {
sjArr[i] = sj;
break;
}
}
}
-- 입력된 성적을 조회한다.
boolean flag = false;
for(int i=0; i<sjArr.length; i++) {
if(sjArr[i] != null) {
flag = true;
System.out.println(sjArr[i]);
}
}
if(!flag)
System.out.println(">> 입력된 성적이 하나도 없습니다.");
▷결과
문제 ▷▷ toString을 사용하여 성적을 바르게 출력될 수 있도록 하시오. (메소드의 Override)
▶▶Sungjuk Class에 toString 메소드를 Override 한다.
▷첫 번째 방법(StringBuffer 사용)
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("1. 국어 : "+kor+"\n");
sb.append("2. 영어 : "+eng+"\n");
sb.append("3. 수학 : "+math+"\n");
return sb.toString();
}
▷두 번째 방법
public String toString() {
String result = "1.학생명 : "+name+"\n"+
"2. 국어 : "+kor+"\n"+
"3. 영어 : "+eng+"\n"+
"4. 수학 : "+math+"\n";
return result;
}
▷▷ Aaaa 클래스에 Sungjuk 클래스를 상속 받으면 Object도 상속이 될까?
-- Sungjuk 클래스에서 이미 Object를 상속받고 있기 때문에 Aaaa 클래스에도 Object가 상속이 된다.
-- Package(my.day15.c.exception)와 Class(Member, Product, MainApp) 생성
-- MainApp은 main method 포함
MainApp에 위와 같이 메뉴를 만들어 보자.
-- 메뉴와 번호를 나타내는 것은 메소드로 만들어 불러와야 한다.
-- 9를 입력하면 프로그램을 종료하고 다른 번호를 누를 경우 "메뉴에 없는 번호입니다"를 출력한다.
public class MainApp {
public static void viewMenu() {
System.out.println("=== 메뉴 ===");
System.out.println("1.로그인 2.로그아웃 3.제품조회 4.주문 9.프로그램 종료");
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String menu ="";
viewMenu();
do {
System.out.println(">> 메뉴번호 선택 :");
menu = sc.nextLine();
switch (menu) {
case "1":
break;
case "2":
break;
case "3":
break;
case "4":
break;
case "9":
break;
default:
System.out.println("메뉴 번호에 없는 번호입니다.");
break;
}
} while (!"9".equals(menu));
System.out.println("=== 프로그램 종료 ===");
sc.close();
}
}
3. 제품조회를 선택하면 위 결과가 나오도록 viewProdDisplay() 메소드를 만들어 보자.
▶▶ MainApp
static void viewProdDisplay(Product[] prodArr) {
System.out.println("============================");
System.out.println("제품코드 제품명 단가 잔고량");
System.out.println("============================");
for(Product prd : prodArr) {
if(prd!=null) {
System.out.println(prd);
}
}
System.out.println("============================");
}
case "3": // 제품조회
viewProdDisplay(prodArr);
break;
▶▶ Product
@Override
public String toString() {
String result = prodCode+"\t"+prodName+"\t"+price+"\t"+jangoCnt;
return result;
}
-- Member Class에서 passwd, name 변수 추가 / getter setter
▷▷ 1. 로그인과 2. 로그아웃 함수 만들기
▷▷ 4. 주문 만들기
-- 로그인 했을 때 주문 함수를 호출할 수 있다.
-- 제품코드를 입력했을 때 배열에 존재하는 제품코드와 비교하고 같지 않다면 주문하시려는 "제품코드는 존재하지 않습니다."라는 메시지 출력
-- 주문량 입력할 때 숫자로 입력하지 않으면 "주문량은 숫자로만 입력하세요."라는 메시지 출력
-- 잔고보다 주문량이 더 많으면 "주문량이 잔고량을 초과하였기에 주문이 불가합니다."라는 메시지 출력
-- ExceptionJangoOver 클래스 생성
-- === 사용자 정의 예외(오류)절 만들기 ===
1. Exception 클래스를 상속받도록 한다.
2. 생성자를 구성해서 예외메시지(오류메시지)를 등록해 주면 끝난다.
public class ExceptionJangoOver extends Exception {
// 기본 생성자
public ExceptionJangoOver() {
super(">>> 주문량이 잔고량을 초과하였기에 주문이 불가합니다. <<<"+"\n");
}
// 파라미터가 있는 생성자
public ExceptionJangoOver(String errorMsg) {
super(errorMsg+"\n");
}
}
▶▶ MainApp
public static void orderProduct(Scanner sc, Product[] prodArr)
throws ExceptionJangoOver {
System.out.print("제품코드 입력 : ");
String oderProdCode = sc.nextLine();
int odrCnt = 0;
do {
System.out.print("주문량 : ");
String strOdrCnt = sc.nextLine();
try {
odrCnt = Integer.parseInt(strOdrCnt);
break;
} catch (NumberFormatException e) {
System.out.println("주문량은 숫자로만 입력하세요.");
}
} while (true);
boolean flag = false;
for (int i = 0; i < prodArr.length; i++) {
if (prodArr[i] != null && prodArr[i].getProdCode().equals(oderProdCode)) {
flag = true;
if (odrCnt > prodArr[i].getJangoCnt()) {
throw new ExceptionJangoOver();
}
}
}
if(!flag) {
System.out.println("주문하시려는 제품코드는 존재하지 않습니다.");
}
}
throw new ExceptionJangoOver();
-- 주문량이 잔고량보다 더 크면 사용자가 정의한 예외절(Exception)을 던지겠다.(throw)
-- 기본 생성자 호출
public static void orderProduct(Scanner sc, Product[] prodArr) throws ExceptionJangoOver
-- orderProduct 메소드는 실행시 사용자가 정의한 ExceptionJangoOver 예외절을 발생시킬 수 있다는 것을 꼭 표시해 주어야 한다.
case "4":
if(loginUser != null) {
try {
orderProduct(sc, prodArr);
} catch (ExceptionJangoOver e) {
e.printStackTrace();
}
}
else {
System.out.println("로그인 후에 주문하실 수 있습니다.");
}
break;
System.out.println("오류 메시지 : "+e.getMessage());
throw new ExceptionJangoOver("주문량 "+odrCnt+" 개가 잔고량 "+
prodArr[i].getJangoCnt()+" 개보다 크므로 주문이 불가합니다.");
-- 기본 생성자 호출 외에 사용자가 지정한 문장을 출력할 수 있다.
문제1. ▷▷
-- 이순신이 4.주문에서 새우깡을 3개 주문했다고 하자. 3개를 주문한 다음에 제품 조회를 하면 잔고량이 7개로 변해야 한다.
문제2. ▷▷
-- 나의 정보 조회 메뉴 만들기
-- 이순신 코인 50000원 중에 새우깡을 3개 주문했으므로 나의 정보 조회 했을 때 47000원이 나와야 한다.
문제3. ▷▷
-- 제품을 구매할 때마다 구매한 금액의 1%를 포인트로 적립해 준다.
-- 나의 정보 조회를 하면 포인트도 출력되어야 한다.