Clojure-예외 처리

Exception handling응용 프로그램의 정상적인 흐름을 유지할 수 있도록 런타임 오류를 처리하기 위해 모든 프로그래밍 언어에서 필요합니다. 예외는 일반적으로 응용 프로그램의 정상적인 흐름을 방해하므로 응용 프로그램에서 예외 처리를 사용해야하는 이유입니다.

예외는 크게 다음 범주로 분류됩니다.

  • Checked Exception− RuntimeException 및 Error를 제외하고 Throwable 클래스를 확장하는 클래스를 확인 된 예외라고합니다. 예 : IOException, SQLException 등. 확인 된 예외는 컴파일 타임에 확인됩니다.

Example.txt라는 파일에서 작업을 수행하는 다음 프로그램을 살펴 보겠습니다. 그러나 Example.txt 파일이 존재하지 않는 경우는 항상있을 수 있습니다.

(ns clojure.examples.example
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (def string1 (slurp "Example.txt"))
   (println string1))
(Example)

Example.txt 파일이 없으면 프로그램에서 다음 예외가 생성됩니다.

Caused by: java.io.FileNotFoundException: Example.txt (No such file or
directory)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at clojure.java.io$fn__9185.invoke(io.clj:229)
at clojure.java.io$fn__9098$G__9091__9105.invoke(io.clj:69)
at clojure.java.io$fn__9197.invoke(io.clj:258)
at clojure.java.io$fn__9098$G__9091__9105.invoke(io.clj:69)

위의 예외에서 우리는 프로그램이 FileNotFoundException을 발생 시켰음을 분명히 알 수 있습니다.

  • Unchecked Exception− RuntimeException을 확장하는 클래스는 확인되지 않은 예외로 알려져 있습니다. 예를 들어 ArithmeticException, NullPointerException, ArrayIndexOutOfBoundsException 등이 있습니다. 검사되지 않은 예외는 런타임에 검사되는 것이 아니라 컴파일 타임에 검사되지 않습니다.

한 가지 고전적인 경우는 배열 길이보다 큰 배열의 인덱스에 액세스하려고 할 때 발생하는 ArrayIndexOutOfBoundsException입니다. 다음은 이러한 종류의 실수에 대한 전형적인 예입니다.

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (try
      (aget (int-array [1 2 3]) 5)
      (catch Exception e (println (str "caught exception: " (.toString e))))
      (finally (println "This is our final block")))
   (println "Let's move on"))
(Example)

위 코드가 실행되면 다음과 같은 예외가 발생합니다.

caught exception: java.lang.ArrayIndexOutOfBoundsException: 5
This is our final block
Let's move on

오류

오류는 복구 할 수 없습니다 (예 : OutOfMemoryError, VirtualMachineError, AssertionError 등). 이러한 오류는 프로그램이 복구 할 수 없으며 프로그램이 중단되는 원인이됩니다. 이제 이러한 예외가 존재하는 경우 프로그램이 계속 실행될 수 있도록 이러한 예외를 포착하는 메커니즘이 필요합니다.

다음 다이어그램은 Clojure의 예외 계층 구조가 어떻게 구성되는지 보여줍니다. 모두 Java에 정의 된 계층 구조를 기반으로합니다.

예외 잡기

다른 프로그래밍 언어와 마찬가지로 Clojure는 예외가 발생할 때 예외를 포착하기 위해 일반적인 'try-catch'블록을 제공합니다.

다음은 try-catch 블록의 일반 구문입니다.

(try
   (//Protected code)
   catch Exception e1)
(//Catch block)

예외를 발생시킬 수있는 모든 코드는 Protected code block.

에서 catch block, 애플리케이션이 예외에서 복구 할 수 있도록 예외를 처리하는 사용자 지정 코드를 작성할 수 있습니다.

파일을 찾을 수 없음 예외를 생성 한 이전 예제를 살펴보고 try catch 블록을 사용하여 프로그램에서 발생한 예외를 포착하는 방법을 살펴 보겠습니다.

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (try
      (def string1 (slurp "Example.txt"))
      (println string1)
      (catch Exception e (println (str "caught exception: " (.getMessage e))))))
(Example)

위의 프로그램은 다음과 같은 출력을 생성합니다.

caught exception: Example.txt (No such file or directory)

위의 코드에서 잘못된 코드를 try block. catch 블록에서 우리는 예외를 잡아서 예외가 발생했다는 메시지를 출력합니다. 이제 프로그램에 의해 생성 된 예외를 캡처하는 의미있는 방법이 생겼습니다.

다중 캐치 블록

여러 유형의 예외를 처리하기 위해 여러 catch 블록을 가질 수 있습니다. 각 catch 블록에 대해 발생하는 예외 유형에 따라 적절히 처리하는 코드를 작성합니다.

두 개의 catch 블록을 포함하도록 이전 코드를 수정 해 보겠습니다. 하나는 파일을 찾을 수 없음 예외를위한 것이고 다른 하나는 일반 예외 블록을위한 것입니다.

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (try
      (def string1 (slurp "Example.txt"))
      (println string1)
      
      (catch java.io.FileNotFoundException e (println (str "caught file
         exception: " (.getMessage e))))
      
      (catch Exception e (println (str "caught exception: " (.getMessage e)))))
   (println "Let's move on"))
(Example)

위의 프로그램은 다음과 같은 출력을 생성합니다.

caught file exception: Example.txt (No such file or directory)
Let's move on

위의 출력에서 ​​우리는 예외가 일반 블록이 아닌 'FileNotFoundException'catch 블록에 의해 포착되었음을 분명히 알 수 있습니다.

마지막으로 차단

finally 블록은 try 블록 또는 catch 블록을 따릅니다. finally 코드 블록은 예외 발생에 관계없이 항상 실행됩니다.

finally 블록을 사용하면 보호 된 코드에서 어떤 일이 발생하더라도 실행하려는 모든 정리 유형 문을 실행할 수 있습니다. 다음은이 블록의 구문입니다.

(try
   (//Protected code)
   catch Exception e1)
(//Catch block)
(finally
   //Cleanup code)

위의 코드를 수정하고 finally 코드 블록을 추가해 보겠습니다. 다음은 코드 조각입니다.

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (try
      (def string1 (slurp "Example.txt"))
      (println string1)
      
      (catch java.io.FileNotFoundException e (println (str "caught file
         exception: " (.getMessage e))))
      
      (catch Exception e (println (str "caught exception: " (.getMessage e))))
      (finally (println "This is our final block")))
   (println "Let's move on"))
(Example)

위의 프로그램은 다음과 같은 출력을 생성합니다.

caught file exception: Example.txt (No such file or directory)
This is our final block
Let's move on

위의 프로그램에서 catch 블록이 필요한 예외를 포착 한 후에도 최종 블록이 구현되었음을 알 수 있습니다.

Clojure는 Java와 마찬가지로 Java에서 예외 처리를 파생하므로 Clojure에서 예외 관리를 위해 다음 메서드를 사용할 수 있습니다.

  • public String getMessage()− 발생한 예외에 대한 자세한 메시지를 반환합니다. 이 메시지는 Throwable 생성자에서 초기화됩니다.

  • public Throwable getCause() − Throwable 객체가 나타내는 예외의 원인을 반환합니다.

  • public String toString() − getMessage ()의 결과와 연결된 클래스 이름을 반환합니다.

  • public void printStackTrace() − 오류 출력 스트림 인 System.err에 스택 추적과 함께 toString ()의 결과를 인쇄합니다.

  • public StackTraceElement [] getStackTrace()− 스택 트레이스의 각 요소를 포함하는 배열을 반환합니다. 인덱스 0의 요소는 호출 스택의 맨 위를 나타내고 배열의 마지막 요소는 호출 스택의 맨 아래에있는 메서드를 나타냅니다.

  • public Throwable fillInStackTrace() −이 Throwable 객체의 스택 추적을 현재 스택 추적으로 채우고 스택 추적의 이전 정보에 추가합니다.

다음은 위에 나열된 방법 중 일부를 사용하는 예제 코드입니다.

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (try
      (def string1 (slurp "Example.txt"))
      (println string1)
      
      (catch java.io.FileNotFoundException e (println (str "caught file
         exception: " (.toString e))))
      
      (catch Exception e (println (str "caught exception: " (.toString e))))
   (finally (println "This is our final block")))
   (println "Let's move on"))
(Example)

위의 프로그램은 다음과 같은 출력을 생성합니다.

caught file exception: java.io.FileNotFoundException: Example.txt (No such file
or directory)
This is our final block
Let's move on