이안의 평일코딩

JAVA의 정석 26일차 - 예외처리 본문

Back-end/Java

JAVA의 정석 26일차 - 예외처리

이안92 2020. 7. 20. 09:22
반응형

2020.07.20(월)

 

1. 예외처리 요약(에러가 났을때 처리 어떻게 할 것인지?)

  1) 정의: 사전에 에러를 방지

  2) 목적: 비정상 종료를 방지하고 정상 상태를 유지

  3) 원인 

    (1) 사용자 : 입력에서

    (2) 프로그램 실수 : 클래스 형변환 잘못하거나 배열을 초과, 0으로 나누는 경우

  4) Error

    (1) 소스상에서 처리가능 (Exception : 수정이 가능한 에러) => 예외처리

    (2) Error : 소스상에서 처리불가능 (메모리부족, 시스템에서 오류)

  5) 형태

    (1) CheckExeption : javac 컴파일 시 에러 => 예외처리가 있는지 확인 => 반드시 예외처리 해야함

    (2) UnCheckException : java(인터프리터) 실행 시 에러 => 생략이 가능

                                   예외발생시 트랜잭션 처리 (roll-back 이전상태로)

 

  CheckException UnCheckException
예외 반드시 예외처리 예외처리 생략가능(필요시에는 예외처리)
종류 파일 입출력 (IOException)
쓰레드 (InterruptedException)
URL (MalformedURLException)
데이터베이스 (SQLException)
ClassNotFoundException =>클래스 이름 오류
RuntimeException => (인터프리터) 실행시 에러
1) 0으로 나눌경우 : 산술오류
2) 배열의 크기를 초과했을 때
3) 정수 변환과정 오류 NumberFormatException
NullPointerException (new로 메모리할당 저장안했을때)
ClassCastException (작은것 = new 큰것 => 오류)

 

 

 6) 예외처리 방식

   (1) 예외복구(가장 보편적) : try ~ catch 프로그래머가 직접 처리 => 직접 처리

      => 예외처리 순서 (상속도)

try {
	평상시 코딩 -> 실행이 가능한 코드
    }catch(예상되는 에러){ }
    catch(예상되는 에러){ }

   (2) 예외회피 : throws 시스템에 맡긴다 => 간접 처리

      => 예외처리 순서가 없다

   (3) 임의발생 : throw 발생 => 테스트

   (4) 사용자정의 : extends Exception 상속받아서 처리

 

2. 예외처리

 = 자바의 모든 소스에는 예외처리가 있다 (생략가능, 생략불가능)

 = 프로그램을 실행하는 과정에서 오작동, 비정상적으로 종료 => 에러/오류

    ** 윈도우 : 쓰레드의 충돌, 주소값

    오작동, 비정상적으로 수행

    ==================

    = 프로그래머의 실수

    = 사용자의 오류 (입력값, 작동을 잘못했을 경우)

    예) 33대란 => 은행이 오작동 (신한은행, 농협) => 소프트포럼(보안)

    = 에러의 종류

      컴파일 에러 : 컴파일시에 에러

      실행시 에러 : 실행시에 발생하는 에러

      논리적 에러 : 실행이 되는데 동작을 다르게 ... => 프로그램의 순서가 틀린 경우

    = 실제 에러종류

      에러 : 프로그래머가 소스상에서 수정할 수 없는 에러

               = 메모리가 부족현상

               = 이클립스 에러

=========================================== 처리가 불가능

      예외 : 가벼운 에러 (수정이 가능한 에러)

               = 소스상에서 수정이 가능

               = 사용자가 0을 입력했을 때 => 다시 입력하시오

               = 아이디 중복체크

               = 파일 입출력 (경로명)

               = 서버 (IP)

               = ***오라클 (오라클 주소, SQL)

 

= 예외처리

  1) Check : 컴파일러가 예외처리했는지 확인 => 반드시 예외처리를 해야 한다

    (1) 파일 입출력, 메모리 입출력, 네트워크 입출력

    (2) 데이터베이스 연결

    (3) 쓰레드 충돌

  2) UnCheck : 실행시 => 컴파일러가 예외처리를 확인하지 않는다

                  예외처리 생략이 가능 => 필요한 경우에만 예외를 처리할 수 있다

             = 사용자의 입력 ==> 문자열 => 정수변환

                                          나누기 => 0을 입력

예외처리 목적 : 프로그램의 비정상 종료를 방지하고 정상상태를 유지할 수 있게 만든다

                    (견고한 프로그램)

예외처리 정의 : 사전에 예상되는 에러를 대비하는 코드를 만든다

 

 = 예외처리 방법

    1) 예외 복구 : 점프 => 프로그래머가 예외가 발생할 경우에 직접 처리 => 정상 상태 유지

                      try~catch~finally => 직접 처리

    2) 예외 회피 : 다른 메소드로 전송 => 시스템에 의해서 처리

                      throws => 간접 처리

    3) 예외 임의발생 : 테스트용

                      throw

    4) 사용자 정의 예외 : 자바라이브러리에서 전체 에러를 지원하지 않는 경우

      (1) 데이터형 => 직접 데이터형 제작 (클래스)

      (2) 메소드    => 사용자가 직접 제작 

      (3) 연산자, 제어문(X)

 

 = 예외처리 try~catch~finally (finally는생략가능)

   try => 평상시 자바 코딩 => 에러

   catch => 에러 발생시 처리 부분 ==> 여러개 사용이 가능

   finally => 에러가 발생하든, 발생하지 않든 무조건 수행되는 문장

                 네트워크, 데이터베이스 프로그램에서는 반드시 존재

                 서버를 연결 해제 => 디도스

   ==> try~catch

         1) 전체 예외처리

         2) 부분적 예외처리

try {
for (int i=0; i<10; i++) {
	i==3 error  ==> i=0,1,2
    } ==> 종료
} catch(Exception e){}

for (int i=0; i<10; i++) {
	try {
		i==3 error ==> i=0,1,2 ==> 4~9
	}catch(Exception e){} ==> i++ 이동
}

 

예외처리 순서

 

package com.sist.exception;

public class MainClass {

	public static void main(String[] args) {
		try {
			int a=10; //1
			int b=0;  //2
			int c=a/b; // 3==>error => cath이동
			System.out.println("c="+c); //실행이 안되는 문장
		}
		catch(Exception ex) {
			System.out.println("0으로 나눌 수 없다!!"); //4
		}
		System.out.println("프로그램 정상 종료"); //5

		
		// 예외처리가 없는 상태
		int a = 10;
		int b = 0;
		int c=a/b; //error => 종료
			System.out.println("c="+c)
			System.out.println("정상적으로 프로그램 종료!!");
	}
}

 

package com.sist.exception;

public class MainClass2 {

	public static void main(String[] args) {
	System.out.println("프로그램 시작"); //1
	try {
		System.out.println("정수 저장 int i=10"); //2
		System.out.println("정수 저장 int j=0"); //3
		System.out.println(10/0); //error => catch이동
		System.out.println("결과값 출력:"+(10/0)); //제외
		// 정상적으로 수행하는 문장
	}catch(Exception e) {
		// 실행하는 과정에서 error발생할 경우에 대비
		System.out.println("나누기 문제 발생 (/zero)"); //4
	}finally {
		System.out.println("다시 입력하시오"); // try, catch상관이 무조건 수행하는 문장
        // 5
	}
	System.out.println("프로그램 종료!!"); //6
	}
}

 

예외 부분처리

 

package com.sist.exception;
//부분 처리
public class MainClass3 {

	public static void main(String[] args) {
		// 부분적으로 try를 사용할 수 있다
		try {
			for(int i=1; i<=10; i++){
				try {
				System.out.println("i="+i);
				int a=i/(int)(Math.random()*3); //error
				System.out.println("a="+a);
			}catch(Exception e) {
				System.out.println("for문 i++로 이동");}
			}
	}catch(Exception ex) {	
		System.out.println("에러 발생");
	}
	System.out.println("프로그램 정상 종료!!");
    }
}

 

예외 다중처리

 

package com.sist.exception;
/*
 * 다중처리 => 예상되는 에러가 여러개 있는 경우
 * try {
 * 		정상적으로 실행되는 문장
 * }catch(예상되는 예외클래스 {
 * 		예외처리
 * }catch(예상되는 예외클래스 {
 * 		예외처리
 * }catch(예상되는 예외클래스 {
 * 		예외처리
 * }
 * 
 * catch를 여러개 사용시에는 순서가 존재한다
 * 예외처리 계층 구조
 * ===========
 * 
 * 최상위 클래스 => 모든 클래스의 상위 클래스
 *
 *             Object
 *                |
 *            Throwable
 *                |
 *        ------------------------
 *        |                      |
 *       Error               Exception 
 *                               |
 *                    ---------------------------
 *                    |                         |
 *                IOException             RuntimeException => 생략
 *                SQLException                  |
 *                ClassFoundException       NumberFormatException
 *                MalformedURLException      ArithmeticException
 *                InterruptedException       NullPointerException
 *				====================	  ArrayIndexOutOfBoundsException
 *                CheckException              ClassCastException   
 *                                                                   
 *                                            
 */
 
public class MainClass4 {

	public static void main(String[] args) {
		try{
			int[] arr=new int[2];
			arr[0]=100;
			arr[2]=0;// error
			
			int a=arr[0]/arr[1];
		}
		catch(NumberFormatException e) {
			System.out.println("정수변환이 안됨");
		}
		/*
		 * catch(ArrayIndexOutOfBoundsException e) { System.out.println("배열범위가 벗어난 경우");
		 * }
		 */catch(ArithmeticException e)
		{
			System.out.println("0으로 나눌 경우");
		}
		/*
		 * catch(RuntimeException e)// 예상 못했던 에러 => 처리 {
		 * System.out.println("실행시 모든 에러를 처리"); } catch(Exception e) // exception {
		 * System.out.println("수정이 가능한 모든 에러를 처리 "); } catch(Throwable e) // error,
		 * exception { System.out.println("예외와 에러를 동시 처리"); }
		 */
		System.out.println("프로그램 종료!!");
	}
}

 

3. 응용

예외처리

형식) 1. 직접처리 (try~catch)

           try{

                실행이 가능한 코딩 (정상 수행할 수 있는 문장)

            }catch(예외클래스 객체){

                실행 과정에 에러가 날 경우에 처리 문장

            }

           *** catch는 여러번 사용이 가능

           *** finally를 사용할 수 있다 (필요한 경우에만 사용을 한다)

               서버, 데이터베이스 관련 => 서버닫기, 오라클 연결 해제

       2. 자바에서 제공하는 예외처리

          한개만 처리

              NumberFormatException

              ArrayIndexOutOfBoundsException

              NullPointerException

              IOException

              SQLException

          여러개 처리

              RuntimeException : 실행시 에러 전체를 묶어서 한번에 처리

              Exception 

              Throwable 

        3. catch는 여러개를 사용할 수 있다

           해당 에러를 찾는 경우에는 처음부터 마지막까지 검색 => 예외처리 순서대로 코딩

        4. try에서 에러가 발생하면 발생위치에서 catch로 이동

           ====================== 밑에 있는 소스는 실행되지 않는다

           int a=10; => 실행

           b=0; => 실행

           c=a/b; => 에러 발생 ==================> catch로 이동

           System.out.println(c) ==> 실행되지 않는다

        5. 목적 : 에러체크 (에러 확인 ==> 소스 변경) ==> 디버깅 

        6. 예외처리 => 수정이 가능한 에러

        

            1문장

            2문장

            3문장

            4문장 ====> error발생 ==> 프로그램을 종료 (비정상 종료)

            5문장

            6문장

            7문장

            ==============================> 7문장이 수행 (정상종료)

 

            1문장

            2문장

            try {

              3문장

              4문장 ====> error발생 ==> 프로그램을 종료 (비정상 종료)

              5문장

                  ===> 4문장, 5문장 ==> 건너뛴다 ==> 6번으로 이동

             }catch(Exception e)

            {

            6문장

            }

            7문장

            ==============================> 7문장이 수행 (정상종료)

 

        7. 자바의 모든 코딩은 예외처리가 존재한다

           단, 실행시는 생략이 가능

 

           void display() {

                return; => 없는 경우에 자동 추가

           }

 

           class A {

               A() {} => 없는 경우에 자동 추가

           }

 

           => 원래는 존재해야되는데 생략 ==> 예외처리

           System.out.println() => 예외처리가 생략이 가능

           System.in.read() => 예외처리를 생략할 수 없다

           *** 생략을 할 수 있지만 => 특별한 경우에는 예외처리를 할 줄 알아야 한다

                ===

                조건문으로 주로 처리 => 조건문으로 처리가 어려운 경우에 예외처리 사용

                => 에러처리의 기본 조건문

 

                try {

                  int a=10;

                  int b=-0;

                  System.out.println(a/b);

                } catch(Exception ex) {

                 System.out.println("0으로 나눌 수 없다");

                }

 

        8. 예외처리는 반드시 처리해야하는 클래스가 존재 

           IO와 관련 => Web과 관련이 있다 

           쓰레드와 관련

           네트워크 관련 => Web과 관련이 있다 

           데이터베이스 관련 => Web과 관련이 있다 

 

package com.sist.exception;
import java.util.*;

import javax.swing.JOptionPane;
public class MainClass {

	public static void main(String[] args) {
		try {
			String num1 = JOptionPane.showInputDialog("첫번째 정수 입력");
			String num2 = JOptionPane.showInputDialog("두번째 정수 입력");
			// 배열에 첨부
			int[] arr = new int[2];
			arr[0] = Integer.parseInt(num1); //숫자 ==> "10"
			arr[2] = Integer.parseInt(num2); //arr[1]까지가 배열범위임
			
			int result = arr[0]/arr[1];
			System.out.println("result="+result);
		}
//		catch(NumberFormatException e) {
//			System.out.println("정수만 입력");
//		}catch(ArrayIndexOutOfBoundsException e) {
//			System.out.println("배열범위 초과");
//		}catch(ArithmeticException e) {
//			System.out.println("0으로 나눌 수 없다");
//		}
		catch(RuntimeException e) { //위 3개 모두 포함. 통으로 잡으면 뭐가 에러인지 알기 힘듦
			//System.out.println(e.getMessage()); //getMessage가 어떤 에러인지 출력해줌
			e.printStackTrace(); //몇번째줄에서 에러가 났는지 알려줌
		}
		System.out.println("처음부터 다시 입력!!"); //출력 되었으므로 정상출력
	}
}
package com.sist.exception;

public class MainClass2 {

	public static void main(String[] args) {
		try {	
		}catch(ArithmeticException e) {
		}catch(ArrayIndexOutOfBoundsException e) {
		}catch(NumberFormatException e) { //web에서 주로 출력하는 error
		}

		try {	
		}catch(RuntimeException e) {
        }
		
		try {
		}catch(ArithmeticException|ArrayIndexOutOfBoundsException|
				NumberFormatException e) { //or(|) 사용해서 세개 동시에 처리
		}
		
		//=> 셋 다 똑같은 방법
        
	}
}

 

망고플레이트 데이터 추출

package com.sist.exception;

import java.io.FileWriter;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
/*
 *   <ul class="list-toplist-slider" style="width: 531px;">
     <li>
     <img class="center-croping" alt="티라미수 맛집 베스트 50곳 사진"
     data-lazy="https://mp-seoul-image-production-s3.mangoplate.com/
     keyword_search/meta/pictures/rjo80nepigkxn637.png?fit=around|600:400&amp;crop=600:400;*,
     *&amp;output-format=jpg&amp;output-quality=80"/>

     <a href="/top_lists/633_tiramisu"
      onclick="trackEvent('CLICK_TOPLIST',
      {&quot;section_position&quot;:0,&quot;section_title&quot;:&quot;믿고 보는 맛집 리스트&quot;,
      &quot;position&quot;:0,&quot;link_key&quot;:&quot;LMUMANJ&quot;});">
     <figure class="ls-item">
     <figcaption class="info">
     <div class="info_inner_wrap">
     <span class="title">티라미수 맛집 베스트 50곳</span>
     <p class="desc">"최애 디저트는 당근 티라미수 아니겠어?"</p>
 */
public class MainClass3 {
	
	public static CategoryVO[] categoryListData() {
		CategoryVO[] cate = new CategoryVO[10];
		//URL => https://www.mangoplate.com/ ==> CheckException
		try {
			Document doc = Jsoup.connect("https://www.mangoplate.com/").get();
			//System.out.println(doc); => 소스읽기
			Elements title = doc.select("div.info_inner_wrap span.title");
			Elements subject = doc.select("div.info_inner_wrap p.desc");
			Elements poster = doc.select("ul.list-toplist-slider img.center-croping");
			//Elements link = doc.select("");
			/*
			 * <p>aaa</a> p.text()
			 * <p src=""> p.attr() 속성
			 * 
			 */
			for(int i=0; i<10; i++) {
//				System.out.println("========================");
//				System.out.println(title.get(i).text());
//				System.out.println(subject.get(i).text());
//				System.out.println(poster.get(i).attr("data-lazy"));
				cate[i] = new CategoryVO();
				cate[i].setCno(i+1);
				cate[i].setTitle(title.get(i).text());
				cate[i].setSubject(subject.get(i).text());
				cate[i].setPoster(poster.get(i).attr("data-lazy"));
				//파일 저장
//				try {
//					String temp=(i+1)+"|"+title.get(i).text()+"|"
//							+subject.get(i).text()+"|"
//							+poster.get(i).attr("data-lazy")+"\r\n";
//					FileWriter fw = new FileWriter("c:\\javaDev\\category.txt",true);
//					fw.write(temp);
//					fw.close();
//				}catch(Exception ex) {
//					ex.printStackTrace();
//				}
			}
			
		}catch(Exception ex) {
			ex.printStackTrace(); // 에러시에 어디서 오류 확인
		}
		return cate;
	}
	public static void main(String[] args) {
    
	}
}
package com.sist.exception;

public class MainClass4 {

	public static void main(String[] args) {
		CategoryVO[] cate = MainClass3.categoryListData();
		for(CategoryVO vo:cate) {
			System.out.println(vo.getCno());
			System.out.println(vo.getTitle());
			System.out.println(vo.getSubject());
			System.out.println(vo.getPoster());
			System.out.println("===================================");
		}

	}

}

 

데이터형 VO

package com.sist.exception;

// 맛집 1개에 대한 정보

public class FoodHouseVO {
	private int no;
	private int cno;
	private String poster; // split
	private String title;
	private double score;
	private String address;
	private String tel;
	private String type;
	private String price;
	private String parking;
	private String time;
	private int good;
	private int soso;
	private int bad;
	public int getNo() {
		return no;
	}
	public void setNo(int no) {
		this.no = no;
	}
	public int getCno() {
		return cno;
	}
	public void setCno(int cno) {
		this.cno = cno;
	}
	public String getPoster() {
		return poster;
	}
	public void setPoster(String poster) {
		this.poster = poster;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public double getScore() {
		return score;
	}
	public void setScore(double score) {
		this.score = score;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	public String getTel() {
		return tel;
	}
	public void setTel(String tel) {
		this.tel = tel;
	}
	public String getType() {
		return type;
	}
	public void setType(String type) {
		this.type = type;
	}
	public String getPrice() {
		return price;
	}
	public void setPrice(String price) {
		this.price = price;
	}
	public String getParking() {
		return parking;
	}
	public void setParking(String parking) {
		this.parking = parking;
	}
	public String getTime() {
		return time;
	}
	public void setTime(String time) {
		this.time = time;
	}
	public int getGood() {
		return good;
	}
	public void setGood(int good) {
		this.good = good;
	}
	public int getSoso() {
		return soso;
	}
	public void setSoso(int soso) {
		this.soso = soso;
	}
	public int getBad() {
		return bad;
	}
	public void setBad(int bad) {
		this.bad = bad;
	}
	
	
}
package com.sist.exception;
// 데이터형 => 캡슐화방식
public class CategoryVO {
	private int cno;
	private String title;
	private String subject;
	private String poster;
	private String link;
	
	//source - getter/setter 캡슐화코드
	
	public int getCno() {
		return cno;
	}
	public void setCno(int cno) {
		this.cno = cno;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getSubject() {
		return subject;
	}
	public void setSubject(String subject) {
		this.subject = subject;
	}
	public String getPoster() {
		return poster;
	}
	public void setPoster(String poster) {
		this.poster = poster;
	}
	public String getLink() {
		return link;
	}
	public void setLink(String link) {
		this.link = link;
	}
	
}

 

 

FoodCategoryCard

package com.sist.client;

import javax.swing.*;
import java.awt.*;
import java.net.*;

public class FoodCategoryCard extends JPanel{
	String title, subject, poster;
	Image img;
	public FoodCategoryCard(String title, String subject, String poster) {
		this.title = title;
		this.subject = subject;
		this.poster = poster;
		try {
			img=Toolkit.getDefaultToolkit().getImage(new URL(poster));
		}catch(Exception ex) {}
	}
	public void paint(Graphics g) {
		g.drawImage(img,0,0,getWidth(),getHeight(),this);
		g.setColor(Color.white);
		g.setFont(new Font("궁서체",Font.BOLD,15));
		g.drawString(title, 10, 100);
		g.drawString(subject, 20, 120);
	}
}

 

FoodCategoryForm

package com.sist.client;

import java.awt.*;
import javax.swing.*;
import com.sist.data.*;

public class FoodCategoryForm extends JPanel{
	public FoodCategoryForm() {
		setLayout(new GridLayout(2,5,5,5));
		CategoryVO[] cate = MainClass3.categoryListData();
		for(CategoryVO vo:cate) {
			FoodCategoryCard fc = new FoodCategoryCard(vo.getTitle(), vo.getSubject(), vo.getPoster());
			add(fc);
		}
	}
}

 

ControllPanel

package com.sist.client;
import java.awt.*;
import javax.swing.*;
public class ControllPanel extends JPanel{
	CardLayout card = new CardLayout();
	ListForm lf = new ListForm();
	DetailForm df = new DetailForm();
	FoodCategoryForm ff = new FoodCategoryForm();
	//변경되는 화면은 컨트롤 패널 가지고있어야함
	public ControllPanel() {
		setLayout(card);
		add("FF",ff);
		add("LF",lf);
		add("DF",df);
	}
}
반응형
Comments