Clojure - 异常处理

Clojure - 异常处理 首页 / Clojure入门教程 / Clojure - 异常处理

任何编程语言都需要异常处理来处理运行时错误,以便可以维持应用程序的正常运行

让我们考虑以下程序,该程序对名为Example.txt的文件进行操作。但是,始终可能存在文件Example.txt不存在的情况。

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

;; This program displays Hello Learnfk
(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。

一种经典的情况是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

Error

错误是无法恢复的,如OutOfMemoryError,VirtualMachineError,AssertionError等。这些是程序永远无法恢复的错误,将导致程序崩溃。现在,我们需要某种机制来捕获这些异常,以便如果存在这些异常,则程序可以继续运行。

下图显示了Clojure中异常的层次结构是如何组织的。全部基于Java中定义的层次结构。

Exceptions in Clojure

捕捉异常

与其他编程语言一样,Clojure提供了正常的" try-catch"块来在异常发生时捕获异常。

以下是try-catch块的一般语法。

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

catch块中,您可以编写自定义代码来处理异常,以便应用程序可以从异常中恢复。

让我们看一下前面的示例,该示例生成了一个文件未找到的异常,并了解了如何使用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块中。在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

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块捕获所需的异常之后,也实现了final块。

以下是使用上面列出的某些方法的示例代码。

(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

祝学习愉快!(内容编辑有误?请选中要编辑内容 -> 右键 -> 修改 -> 提交!)

技术教程推荐

技术领导力实战笔记 -〔TGO鲲鹏会〕

玩转Git三剑客 -〔苏玲〕

体验设计案例课 -〔炒炒〕

说透5G -〔杨四昌〕

攻克视频技术 -〔李江〕

徐昊 · TDD项目实战70讲 -〔徐昊〕

快速上手C++数据结构与算法 -〔王健伟〕

结构执行力 -〔李忠秋〕

云原生基础架构实战课 -〔潘野〕

好记忆不如烂笔头。留下您的足迹吧 :)