Search
Duplicate

자바를 자바 13(Exception Handling, Errors)

간단소개
팔만코딩경 컨트리뷰터
ContributorNotionAccount
주제 / 분류
Java
Scrap
태그
9 more properties

Errors in Programs

자바에서 발생할 수 있는 에러들
Compile-time error 컴파일이 만들어 내는 에러로 object files를 생성 못함 Syntax error
Run-tume error 컴파일이 에러나 object files 생성에 문제는 없음 하지만 프로그램은 실행불가능
Logical error 에러없이 프로그램이 작동함, 하지만 우리가 원했던 결과가 나오지 않음

Run-time error

Run-time error은 errors와 exceptions으로 분류된다.
Error 프로그램이 더 이상 진행을 할 수 없는 상태 ex> out of memory, stack overflow
Exceptions 에러가 발생하였으나 해결할 방법이 존재하는 경우 ex> arithmetic exception(0으로 나누는 경우), class cast exception, null pointer exception, index out-of-bounds exception 그래서 프로그래머는 handler을 선언하여서 exception이 발생하였을 때를 대처할 수 있다.

Erros and Exceptions

자바에서는 이러한 예외도 객체화 되어 있다. 그래서 위의 표와 같이 Throwa ble 클래스 밑에 Error과 Exception 그리고 RuntimeException이 존재
RuntimeException : ArrayIndexOutOfBoundsException, NullPointerException, ClassCastException, Arithmetic Exception 등이 존재
Exception : FileNotFoundException, ClassNotFoundException, DataFormatException

Exception Handling: try-catch

자바에서 에러를 처리하기 위해 try-catch블록을 사용하여 try 한다음 에러가 발생하면 catch에서 처리하여 프로그램을 계속 진행시키어 준다.
try { // 에러가 날 수 있는 것을 여기에 삽입 } catch (Exception1 e1) { // Exception1에 해당되는게 발생시 여기에서 처리 } catch (Exception2 e2) { // statements that will be executed when Exception2 occurs. try { } catch (Exception3 e3) { } // try-catch blocks can be nested. In that case, the parameters (e2 and e3) must be different. } catch (ExceptionN eN) { // statements that will be executed when ExceptionN occurs. }
Plain Text
복사

Exception Handling: Example

public class Lecture { public static void main(String args[]) { int number = 100; int result = 0; for(int i=0; i<10; i++) { result = number / (int)(Math.random() * 10); System.out.println(result); } } }
Plain Text
복사
위와 같이 0~90 사이의 숫자로 나누어 주다가 0으로 잘 못 나누어 준 경우 위와 같이 에러 발생 출력문이 나올 수 있다.
그래서 이를 해결하기 위해 다음과 같이 작성해 주어야 한다.
public class Lecture { public static void main(String args[]) { int number = 100; int result = 0; for(int i=0; i<10; i++) { try { result = number / (int)(Math.random() * 10); System.out.println(result); // 예외 발생시 여기에서 처리 } catch (ArithmeticException e) { System.out.println("0"); } } } }
Plain Text
복사

The catch Block

catch 블락에 대해서 다시금 생각해 보자
public class Lecture { public static void main(String args[]) { try { System.out.println(3); System.out.println(0/0); // ArithmeticException! System.out.println(4); } catch (Exception e) { System.out.println(5); } } }
Plain Text
복사
지금 Exception 객체를 받는 catch문이 선언되어 있다. 그런데 발생한건 ArithmeticException이다. 즉 subclass에 해당하는 것은 superclass에서 모두 받아 줄 수 있다는 것을 이야기 한다.
그렇다면 만약 예외경우가 여러개이면 어떻게 할까?
public class Lecture { public static void main(String args[]) { try { System.out.println(3); System.out.println(0/0); // ArithmeticException! System.out.println(4); } catch (ArithmeticException e) { System.out.println("ArithmeticException occurred!"); } catch (Exception e) { System.out.println("Exception occurred!"); } } }
Plain Text
복사
이 경우에는 위와 같이 작성하고 첫번째 catch 블락부터 에러를 처리 할 수 있는지 확인한다. 여기에서 중요하게 봐야하는 점은 subclass는 가급적 superclass 위에 위치시키는 것이 좋다.

printStackTrace() and getMessage()

에러가 났을 때 우리는 무엇을 하는가 인데, 보통의 printStackTrace()와 getMessage()를 많이 한다.
public class Lecture { public static void main(String args[]) { try { System.out.println(3); System.out.println(0/0); // ArithmeticException! System.out.println(4); } catch (ArithmeticException ae) { ae.printStackTrace(); System.out.println("exception message: " + ae.getMessage()); } } }
Plain Text
복사
printStackTrace : 에러가 생기기 까지 어떤 경로를 따라서 이 위치까지 왔는지를 확인하는 함수 getMessage : 객체로 부터 에러 메세지를 가져온다.

Generating an Exception

예외 경우를 일부러 만들 수도 있다.
public class Lecture { public static void main(String args[]) { try { Exception e = new Exception("I created the exception."); // becomes the exception message. throw e; } catch (Exception e) { System.out.println("exception message: " + e.getMessage()); e.printStackTrace(); } System.out.println("The program terminated normally."); } }
Plain Text
복사
예외 경우를 다룰 객체를 만들어 놓고 throw를 사용하여서 Exception을 처리한다.

Mandatory and Optional Exception Handling

File Not Found와 같은 경우처럼 반드시 Exception을 하여야만 하는 경우가 존재한다.
Mandatory(checked exceptions) : 반드시 Handling 하여야 하는 Exception
public class Lecture { public static void main(String args[]) { throw new Exception("My exception."); } } // compile error!
Plain Text
복사
Optional(unchecked exceptions) : 선택적으로 Handling 하여야 하는 Exception
public class Lecture { public static void main(String args[]) { throw new ArithmeticException("My exception."); } } // no error!
Plain Text
복사
그럼 어떻게 위의 경우를 구분할까? Exception 클래스의 subclass 중에서 Runtime Exception을 제외하고 나머지는 Mandatory이다.
Runtime Exception의 대표적인 경우가 ArithmeticException이다.

Methods that throw exceptions

예외 처리를 하지 않는 방법도 존재한다.
public class Lecture { public static void main(String args[]) { method1(); } static void method1() { method2(); // Error: must handle Exception or throw Exception. } static void method2() throws Exception { throw new Exception(); } } // compile error!
Plain Text
복사
throws Exception은 에러가 난 경우를 처리하지 않겠다는 의미이다. 그렇다면 method2에서는 에러처리를 하지 않아도 되지만 그 경우에는 method2를 호출한 method1이 에러처리를 해주어야만 한다.
그러면 method1에서도 throws Exception을 한다면??
public class Lecture { public static void main(String args[]) { method1(); // Error: must handle Exception or throw Exception. } static void method1() throws Exception { method2(); } static void method2() throws Exception { throw new Exception(); } } // compile error!
Plain Text
복사
결국 main에서 에러가 나게 된다.
만약 main까지 throws Exception을 한다면??
public class Lecture { public static void main(String args[]) throws Exception { method1(); } static void method1() throws Exception { method2(); } static void method2() throws Exception { throw new Exception(); } } // no error at compile time but will cause program to crash at run time.
Plain Text
복사
실행은 되지만 crash가 난다.
그래서 위의 문제를 해결하기 위해 다음과 작성해주어야지 문제가 발생하지 않는다.
public class Lecture { public static void main(String args[]) { method1(); } static void method1() { try { method2(); } catch(Exception e) { System.out.println("Exception handled in method1"); e.printStackTrace(); } } static void method2() throws Exception { throw new Exception(); } } // OK! method1 handles the Exception
Plain Text
복사
여기에서 한가지 더 짚고 넘어가자. 우리는 전 시간에 파일을 다루기 위한 메소드를 선언하면서 throws IOException을 선언했던것을 기억할 것이다. 그런데 이렇게 하면 좋지 않은 것이 FileOutputStream 내부에는 throws FileNotFoundException이 선언되어 있기 때문이다.
import java.io.FileOutputStream; import java.io.IOException; public class Lecture { public static void main(String[] args) throws IOException { FileOutputStream output = new FileOutputStream("src/cse3040/out.txt"); String str = "hello world"; byte[] bytes = str.getBytes(); output.write(bytes); output.close(); } }
Plain Text
복사
그래서 위와 같은 코드에도 가급적 try-catch문 선언이 필요하다.

The finally Block

이제 finally Block에 대해서 알아보자 finally block은 try block에서 exception이 발생하든 안하든 상관없이 반드시 실행되는 block이다.
try { // statements that can cause exceptions. } catch (Exception1 e1) { // statements for handling Exception1 } finally { // this block is executed whether or not an exception occurs in the try block. // this block must be placed at the end of a try-catch block. }
Plain Text
복사
하지만 아래와 같이 try 안에 return을 수행하여야 하는 경우는 어떻게 될 것인가? 결론은 finally를 수행한다음 return을 하게 된다.
public class Lecture { public static void main(String args[]) { Lecture.method1(); System.out.println("returned to main method after calling method1."); } static void method1() { try { System.out.println("the try block of method 1 is being executed."); return; } catch(Exception e) { e.printStackTrace(); } finally { System.out.println("the finally block of method 1 is being executed."); } } }
Plain Text
복사
위와 유사하게 이러한 코드를 File IO 에도 사용하여야 한다. 기존에는 BUfferedReader을 사용하기 위해서 main에 throws IOException을 적어 주었던 것이 기억나는가? 이거 역시 사실은 try-catch문으로 모두 잡아 주어야 한다.
여기에서 한가지 주의할점!! try-catch 내에 선언된 변수는 지역변수이다. 파일 IO 변수는 try-catch 외부에 선언하고 나중에 try-catch 내부에서 사용하자
import java.io.FileInputStream; import java.io.IOException; public class Lecture { public static void main(String[] args) { byte[] b = new byte[1024]; FileInputStream input = null; try { input = new FileInputStream("src/kr/ac/sogang/icsl/aaa.txt"); input.read(b); System.out.println(new String(b)); } catch(IOException e) { e.printStackTrace(); } finally { try { input.close(); } catch(Exception e) { e.printStackTrace(); } } System.out.println("The program exited normally."); } }
Plain Text
복사