언어/Java

예외 처리 (이론)

뭉지(moonz) 2020. 9. 7. 17:13
반응형

이번 글에서는 예외처리의 이론적 개념을 정리할 것이다:)

 

▶오류의 종류

에러(Error) 예외(Exception)
하드웨어의 잘못된 동작 또는 고장으로 인한 오류 사용자의 잘못된 조작 또는 개발자의 잘못된 코딩으로 인한 오류
에러가 발생되면 프로그램 종료 예외가 발생되면 프로그램 종료
정상 실행 상태로 돌아갈 수 없음 예외처리 추가하면 정상 실행 상태로 돌아갈 수 있음

** 예외 ; 경험론적 코딩 기법

why? 미리 경험하여 겪어봐야 예외가 발생하는 것을 알고, 예외를 예상해서 써주는 것이기 때문.

** 예외처리를 추가한다 ; 예외가 발생했을때 그부분을 실행하지않도록 한다.

▶예외의 종류

- 일반(컴파일 체크) 예외 ; 예외 처리 코드 없으면 컴파일 오류 발생

- 실행 예외 (Runtime Exception) ; 예외 처리 코드를 생략하더라도 컴파일이 되는 예외, 경험에 따라 예외 처리 코드 작성 필요.

 

1. NullPointerException ; 객체 참조가 없는 상태

- null값 갖는 참조변수로 객체 접근 연산자인 도트(.) 사용했을 때 발생

String data = null;
System.out.println(data.toString());	
//data에 값이 없는데 읽으려하는 것. 잘못 참조했다는 예외 발생!

2. ArrayIndexOutOfBoundsException ; 배열에서 인덱스 범위 초과하여 사용할 경우 예외 발생

public static void main(String[] args) {
  String data1 = args[0];
  String data2 = args[1];
  
  System.out.println("args[0]:"+data1);
  System.out.println("args[1]:"+data2);
}
//인덱스 범위가 얼만지 모르는데 접근하는 것. 예외 발생!
//입력 범위 미설정 에러

예외 처리를 ifelse로도 처리해줄 수 있다. if (args.length ==2)이면 실행하는 식으로.

if(args.length ==2) {
  String data1 = args[0];
  String data2 = args[1];
  System.out.println("args[0]:" + data1);
  System.out.println("args[1]:" + data2);
} else {
  System.out.println("[실행 방법]");
  System.out.print("java ArrayIndexOutOfBoundsExceptionExample ");
  System.out.print("값1 값2");
}

 

3. NumberFormatException ;문자열 데이터를 숫자로 변경 시 문자가 포함돼있을 경우 예외 발생.

▶정수로 변경하는 방법

반환 타입 메소드명 (매개변수)
Int Integer.parseInt(String s)
double Double.parseDouble(String s)
public static void main(String[] args) {
  String data1 = "100";
  String data2 = "a100";
  
  int value1 = Integer.parseInt(data1);
  int value2 = Integer.parseInt(data2);
  
  int result = value1 + value2;
  System.out.println(data1 + "+" + data2 + "=" + result);
}
//문자 a의 포함으로 숫자 data2로 변경 불가 에러.

4. ClassCastException ; 타입 변환이 되지 않을 경우 발생. (다운 캐스팅할 때 발생)

예제로 보면,

정상 코드

Animal ani = new Dog();
Dog dog = (Dog) ani;

RemoteControl rc = new Television();
Television tv = (Television) rc;

예외 발생 코드

Animal ani = new Dog();
Cat cat = (Cat) ani;	//Animal로 업캐스팅된 개가 고양이로 다운캐스팅하려할 경우 발생

RemoteControl rc = new Television();
Audio audio = (Audio) rc;

예외 발생을 위해서 if문으로 방지할 수 있는데,

if (ani instanceof Dog) {
  Dog dog = new ani;
}

if (rc instanceof Television) {
  Television tv = new rc;
}

예외처리를 if문 -instanceof로 해줄 수 있다.

 

▶예외처리 전용 코드가 따로 있다.  try - catch - finally 블록 
(예외가 어느 반경에서 일어날 건지 예상해놓고 미리 설정해놓는게 try 범위이다.)

 

(1) 예외 던지기(catch)

try{ 
  오류가 날 수도 있는 문장->오류가 안나면 catch()는 실행X 
}catch(예외이름 객체명) { 
  오류 발생 시 실행할 문장 
} 

-if문으로 잡을 수 없는 걸 catch로 잡는 것.

(2) 하나의 문장에서 예외가 여러개 발생

try{ 
  오류가 날 수도 있는 문장
}catch(예외이름1 객체명1) {
  오류 발생 시 실행할 문장
}catch(예외이름2 객체명2) {
  오류 발생 시 실행할 문장
} 


(3) finally{} 추가

try{ 
  오류가 날 수도 있는 문장 
}catch(예외이름 객체명) { 
  오류 발생 시 실행할 문장
}finally{ 
  예외발생 여부에 상관없이 무조건 실행할 문장 
} 


(4) 예외 OR

try{ 
  오류가 날 수도 있는 문장 
}catch(예외이름1 | 예외이름2 객체명) { //OR연산자 
  둘 중 하나라도 발생 시 실행할 문장 
} 

기초 예제

----------------------------------------------------------------------------------------

1. 예외 발생 코드

public class Try{
  public static void main(String[] args) {
    System.out.println(10/0);
    
    System.out.println("종료");
  }
}

Why? 나누기에서 분모는 0이 될 수 없으니까.

2. 예외 처리 코드

public class Try {
  public static void main(String[] args) {
    try {
      System.out.println(10/0);
    } catch (ArithmeticException e) {	//예외 이름은 너무 다양해서 보통 Exception으로 두지만, 알면 예외이름으로 적기.
      System.out.println("0으로 나눌 수 없습니다.");
    }
    System.out.println("종료");
  }
}

객체 e로 예외를 받는 것.

예외가 발생하는 범위 이외의 문장이 실행되려면 예외를 잘 처리해줘야함.

이렇게 예외처리를 해주게되면 에러가 발생하지 않으면서, 어떤 오류가 발생한지도 알 수없다.

어떤 예외인지 알수있는 방법은?

.getMassage() ; 오류 이름 출력

.printStackTrace() ; 오류 내용 출력

 

 

 

 

 

 

 

 

 

 

기초 예제 2

----------------------------------------------------------------------------------------

1. 예외 발생 코드

public class Try2 {
	public static void main(String[] args) {
      int[] arData = new int[5];
      
      for(int i=0;i<100;i++) {
        arData[i]=i+1;
      }
    }
}

Why? 길이가 5인 배열에 인덱스 100까지 대입하려했기 때문.

 

2. 예외 처리 코드

public class Try2 {
	public static void main(String[] args) {
      int[] arData = new int[5];
      
      for(int i=0;i<100;i++) {
        System.out.println(i);
      	try {
          arData[i] = i+1;	//i=6일 때, 오류가 발생하면
        }
      } catch {	//break안하면 95번 에러처리.
        break;	//이 문장 실행된 후,
      }
      System.out.println("정상 종료"	//catch 밖 문장까지 실행됨.
    }
}

 

 

 

 

 

 

5까지 돌아가고, try문에서 에러처리되는거니까 6번 반복된다는 점!

 

엘레베이터 예제

----------------------------------------------------------------------------------------

▶Lift 종류는 다양하니까 추상클래스 or 인터페이스로 생성해야 한다.

 

1. 추상클래스 Lift 코드

public abstract class Lift {
  static final int floor = 0;	//공유의 목적인 static
  
  abstract void up();
  abstract void down();
  abstract void start(String choice);
  absrtact void stop();
  abstract void go();
}

Q. 왜 인터페이스가 아닌 추상클래스? 인터페이스의 상수는 외부에서 바꿀 수 없다. 추상클래스의 상수로 만들어야, 외부에서 층수를 랜덤으로 변경 가능하다.

 

2. 상속 클래스 Elevator 코드

public class Elevator extends Lift {

  abstract void up() {
  
  }
  abstract void down() {
  
  }
  abstract void start(String choice) {
  
  }
  absrtact void stop() {
  
  }
  abstract void go() {
  
  }
}

곧 다시 수정하러 오겠다

반응형