프로그래머가 상정한 정상적인 처리에서 벗어나는 경우에 이를 처리하기 위한 방법 (예기치 못한 오류)
ex 1)
class Calculator{
int left, right;
public void setOprands(int left, int right){
this.left = left;
this.right = right;
}
public void divide(){
// 나누기 메소드
System.out.print("계산결과는 ");
System.out.print(this.left/this.right);
System.out.print(" 입니다.");
}
}
public class CalculatorDemo {
public static void main(String[] args) {
Calculator c1 = new Calculator();
c1.setOprands(10, 0);
c1.divide();
}
여기서 문제는 10 나누기 0 이므로 에러가 발생한다...
해결 방법
class Calculator{
int left, right;
public void setOprands(int left, int right){
this.left = left;
this.right = right;
}
public void divide(){
try {
System.out.print("계산결과는 ");
System.out.print(this.left/this.right);
System.out.print(" 입니다.");
} catch(Exception e){
System.out.println("오류가 발생했습니다 : "+e.getMessage());
}
}
}
public class CalculatorDemo {
public static void main(String[] args) {
Calculator c1 = new Calculator();
c1.setOprands(10, 0);
c1.divide();
Calculator c2 = new Calculator();
c2.setOprands(10, 5);
c2.divide();
// 결과 :
// 계산결과는 오류가 발생했습니다 : / by zero
// 계산결과는 2 입니다.
}
}
try {
예외의 발생이 예상되는 로직
} catch (예외클래스 인스턴스) {
예외가 발생했을 때 실행되는 로직
}
try 안에는 예외 상황이 발생할 것으로 예상되는 로직을 위치
catch 안에는 예외가 발생했을 때 뒷수습을 하기 위한 로직이 위치
ex 1 에서는 사용자가 setOprands의 두 번째 인자로 숫자 0을 입력했을 때 문제가 발생할 수 있음을 예측할 수 있다
( try 내의 실행이 중단되고 catch 구문 안의 내용이 실행 )
Exception은 자바에서 기본적으로 제공하는 클래스
예외가 발생하면 자바는 마치 메소드를 호출하듯이 catch를 호출하면서
그 인자로 Exception 클래스의 인스턴스를 전달하는 것
e.getMessage()는 자바가 전달한 인스턴스의 메소드 중 getMessage를 호출하는 코드
getMessage는 오류의 원인을 사람이 이해하기 쉬운 형태로 리턴
뒷수습의 방법
예외의 핵심은 뒷수습
ex 1)
class Calculator{
int left, right;
public void setOprands(int left, int right){
this.left = left;
this.right = right;
}
public void divide(){
try {
System.out.print("계산결과는 ");
System.out.print(this.left/this.right);
System.out.print(" 입니다.");
} catch(Exception e){
System.out.println("\n\ne.getMessage()\n"+e.getMessage());
System.out.println("\n\ne.toString()\n"+e.toString());
System.out.println("\n\ne.printStackTrace()");
e.printStackTrace();
}
}
}
public class CalculatorDemo {
public static void main(String[] args) {
Calculator c1 = new Calculator();
c1.setOprands(10, 0);
c1.divide();
}
}
ex 1의 출력 결과
계산결과는
e.getMessage()
/ by zero
e.toString()
java.lang.ArithmeticException: / by zero
e.printStackTrace()
java.lang.ArithmeticException: / by zero
at org.opentutorials.javatutorials.exception.Calculator.divide(CalculatorDemo.java:11)
at org.opentutorials.javatutorials.exception.CalculatorDemo.main(CalculatorDemo.java:25)
e.getMessage();
오류에 대한 기본적인 내용을 출력해준다. 상세하지 않다.
e.toString()
e.toString()을 호출한 결과는 java.lang.ArithmeticException: / by zero 이다.
e.toString()은 e.getMessage()보다 더 자세한 예외 정보를 제공
e.printStackTrace()
메소드 getMessage, toString과는 다르게 printStackTrace는 리턴값이 없다. 이 메소드를 호출하면 메소드가 내부적으로 예외 결과를 화면에 출력한다. printStackTrace는 가장 자세한 예외 정보를 제공한다.
자바는 try 와 catch 구문들을 실행하고 바로 종료가 되는 것이 아니라
나머지 로직들도 실행 된다
다양한 예외들
class A{
private int[] arr = new int[3];
A(){
arr[0]=0;
arr[1]=10;
arr[2]=20;
}
public void z(int first, int second){
System.out.println(arr[first] / arr[second]);
}
}
public class ExceptionDemo1 {
public static void main(String[] args) {
A a = new A();
a.z(10, 1);
}
}
에러가 발생한다.
이유 : 배열 arr은 3개의 값을 담을 수 있다. 하지만 10번째 인덱스를 호출
따라서 존재하지 않는 값을 가져오려고 시도
해결 방법
위에 예제를 해결해야 할 뿐더러 0으로 나누는것도 해결해야 한다면?
class A{
private int[] arr = new int[3];
A(){
arr[0]=0;
arr[1]=10;
arr[2]=20;
}
public void z(int first, int second){
try {
System.out.println(arr[first] / arr[second]);
} catch(ArrayIndexOutOfBoundsException e){ // 존재하지 않는 값 예외
System.out.println("ArrayIndexOutOfBoundsException");
} catch(ArithmeticException e){ // 0으로 나누는 예외
System.out.println("ArithmeticException");
} catch(Exception e){ // 다른 예외
System.out.println("Exception");
}
}
}
public class ExceptionDemo1 {
public static void main(String[] args) {
A a = new A();
a.z(10, 0);
a.z(1, 0);
a.z(2, 1);
}
}
출력결과
ArrayIndexOutOfBoundsException
ArithmeticException
2
예제는 다중 catch를 보여준다. 조건문의 else if처럼 여러 개의 catch를 하나의 try 구문에서 사용할 수 있다
예외의 종류가 ArrayIndexOutOfBoundsException이라면 14행이 실행되고, ArithemeticException이라면 16행이 실행되고 그 외의 것이라면 18행이 실행
만약 Exception 이 다른 예외보다 먼저 위에 있다면 에러발생!!!
이유 :
Exception이 ArrayIndexOutOfBoundsException, ArithemeticException 보다 포괄적인 예외를 의미
Exception 이후에 등장하는 catch 문은 실행될 수 없는 구문
finally
finally는 try 구문에서 예외가 발생하는 것과 상관없이 언제나 실행되는 로직
try catch 뒤에 와야한다.
try {
예외의 발생이 예상되는 로직
} catch (예외클래스 인스턴스) {
예외가 발생했을 때 실행되는 로직
} finally {
예외여부와 관계없이 실행되는 로직
}
ex 1)
class A{
private int[] arr = new int[3];
A(){
arr[0]=0;
arr[1]=10;
arr[2]=20;
}
public void z(int first, int second){
try {
System.out.println(arr[first] / arr[second]);
} catch(ArrayIndexOutOfBoundsException e){
System.out.println("ArrayIndexOutOfBoundsException");
} catch(ArithmeticException e){
System.out.println("ArithmeticException");
} catch(Exception e){
System.out.println("Exception");
} finally {
System.out.println("finally");
}
}
}
public class ExceptionDemo1 {
public static void main(String[] args) {
A a = new A();
a.z(10, 0);
a.z(1, 0);
a.z(2, 1);
}
}
실행 결과
ArrayIndexOutOfBoundsException
finally
ArithmeticException
finally
2
finally
예외와 상관없이 try 내의 구문이 실행되면 finally가 실행
finally는 언제 사용해야 하는지?
어떤 작업의 경우는 예외와는 상관없이 반드시 끝내줘야 하는 작업이 있을 수 있다
ex ) DB에 접속을 100개로 제한되어 있고 예외가 반복작업이라면 접속을 끊어줘야한다. (설명을 너무 못하는듯,,,, ㅠ)