1. 程式人生 > >Kotlin系列之異常

Kotlin系列之異常

這一節我們說說Kotlin中的異常。

Java中的異常

我們知道,在Java中,異常是一個繞不過的話題,說到異常,最先想到的就是try...catch...finally,在Kotlin中也是同樣的,使用方式幾乎是不變的,但是也有一些小小的變動。這裡我們還是以往的慣例,先放Java程式碼,再上Kotlin程式碼。

Java程式碼

public int readNumber(BufferedReader reader) throws IOException {
    int result = 0;
    String line = reader.readLine();
    result = Integer.parseInt(line);
    reader.close();
    return
result; }

上面的程式碼readLine()方法會丟擲IOException,這是一個受檢查異常,必須要顯式處理,要麼在方法宣告上丟擲,要麼在內部捕獲處理。其實程式碼裡面的parseInt()方法也會丟擲一個執行時異常,Java是不強制要求我們捕獲處理執行時異常的,但這裡我們為了和後面的內容配合講解,處理一下這個異常。
修改後的程式碼是這樣。

Java程式碼

public int readNumber(BufferedReader reader) throws IOException {
    int result = 0;
    String line = reader.readLine();
    try
{ result = Integer.parseInt(line); }catch (NumberFormatException e){ e.printStackTrace(); result = -1; }finally { if (reader != null){ reader.close(); } } return result; }

這裡使用try...catch...finally來改善了一下程式碼。在Java中,一個函式可以正常結束,也會在出現錯誤的時候丟擲異常,方法的呼叫者可以捕獲這個異常並處理它,如果沒有被處理,異常會沿著呼叫棧再次丟擲。

Kotlin中throw作為表示式

在Kotlin中異常處理機制是相似的,但與Java中不同的是throw是一個表示式,可以作為另一個表示式的一部分使用。我們看看下面的程式碼。

Kotlin程式碼

fun test(){
    val n = 1;
    val res = if (n in 0..100){
        n
    }else{
        throw IllegalArgumentException("error")
    }

    println(res)
}

這裡說一下,前面的內容也說過if也是表示式,上面的程式碼,如果n的值在0-100直接則res的值初始化為n的值,如果不是,丟擲一個異常,res的值不初始化。與我們以前的程式碼一樣,與Java語言不同,丟擲的異常不需要使用new

Kotlin中的異常

我們在開始給出了一個Java中的try...catch...finally的例子,這裡我們再使用Kotlin程式碼實現一下,對比一下兩者的差異。

Kotlin程式碼

fun readNumber(reader: BufferedReader): Int{
    var result = 0
    val line = reader.readLine()
    try {
        result = Integer.parseInt(line)
    } catch (e: NumberFormatException) {
        e.printStackTrace()
        result = -1
    } finally {
        reader.close()
    }
    return result
}

上面的程式碼有幾點需要注意。
1. 正如前面一直在說的,函式返回值型別是寫在最後,用:分割。
2. 你會發現Kotlin中不需要顯式在方法宣告上宣告丟擲的IOException
3. 變數的宣告也是變數名:變數型別的格式。

在Kotlin中不再區分受檢查異常和不受檢查異常。原因在於有時候比如我們的檔案關閉出現錯誤的異常,除了看到這個異常,其實我們也做不了什麼,Kotlin則直接將這種程式碼去掉了。
可能有的人還有疑問,在前面的java程式碼的finally塊中有這樣的的判空程式碼

if (reader != null){
    reader.close();
}

為什麼在Kotlin中消失了?這是因為在Kotlin中宣告函式引數型別時,如果這樣寫reader: BufferedReader,表示這是一個不可空值,如果要宣告為可空值可以這樣寫reader: BufferedReader?,這樣就需要在close前判空了。

Kotlin中的try作為表示式

前面我們說了throw作為表示式,其實try也是一個表示式,我們可以將try的值賦值給一個變數。我們繼續該一下上面的程式碼。

Kotlin程式碼

fun readNumber(reader: BufferedReader): Int?{
    var result = 0
    val line = reader.readLine()
    result = try {
        Integer.parseInt(line)
    } catch (e: NumberFormatException) {
        e.printStackTrace()
        -1
    } finally {
        reader.close()
    }
    return result
}

你會發現程式碼又變少了,這裡我們先補充一條規則才能理解上面的程式碼。
try作為表示式時,如果try塊執行正常,則try塊中最後一個表示式就是結果,如果丟擲異常進入catch塊,則catch塊中最後一個表示式的值就是結果。
知道了這條規則是不是上面的程式碼就好理解了

寫在最後

異常機制的出現是為了讓我寫出更加健壯的程式碼,在Kotlin中對Java的異常處理機制進行了一些改進和完善,讓我們用更簡潔的方式處理異常。

相關推薦

Kotlin系列異常

這一節我們說說Kotlin中的異常。 Java中的異常 我們知道,在Java中,異常是一個繞不過的話題,說到異常,最先想到的就是try...catch...finally,在Kotlin中也是同樣的,使用方式幾乎是不變的,但是也有一些小小的變動。

(譯)Effective Kotlin系列遇到多個構造器引數要考慮使用Builder(二)

翻譯說明: 原標題: Effective Java in Kotlin, item 2: Consider a builder when faced with many constructor parameters 原文地址: https://blog.kotlin-academy.

(譯)Effective Kotlin系列考慮使用靜態工廠方法替代構造器(一)

翻譯說明: 原標題: Effective Java in Kotlin, item 1: Consider static factory methods instead of constructors 原文地址: https://blog.kotlin-academy.com/eff

(譯)Effective Kotlin系列探索高階函式中inline修飾符(三)

簡述: 不知道是否有小夥伴還記得我們之前的Effective Kotlin翻譯系列,之前一直忙於趕時髦研究Kotlin 1.3中的新特性。把此係列耽擱了,趕完時髦了還是得踏實探究本質和基礎,從今天開始我們將繼續探索Effective Kotlin系列,今天是Effective Kotlin第三講。 翻譯說明

[譯]Effective Kotlin系列使用Sequence來優化集合的操作(四)

簡述: 今天迎來了Effective Kotlin系列的第四篇文章: 使用Sequence序列來優化大集合的頻繁操作.關於Sequence這個主題應該大家都不陌生,我寫過幾篇有關它的文章,可以說得上很詳細了。如果你對它的使用不太熟悉,歡迎檢視下面幾篇有關文章: 淺談Kotlin中的Sequences原

[譯]Effective Kotlin系列考慮使用原始型別的陣列優化效能(五)

翻譯說明: 原標題: Effective Kotlin: Consider Arrays with primitives for performance critical processing 原文地址: blog.kotlin-academy.com/effective-k… 原文作者: Marcin

Kotlin系列基礎語法

標籤: Kotlin      Kotlin基礎語法 目錄: 簡述: Kotlin的基本語法的介紹,先從整體上體會kotlin的程式設計風格。 一、包的宣告 在Kotlin中定義包與Java有點不同,在Kotlin中目錄與包結構無需匹配,

Kotlin系列變數和常量

標籤: Kotlin      變數      屬性     var與val區別      自定義屬性訪問器     智慧型別推斷 目錄: 簡述: Kotlin基礎系列第二篇,之前記

Kotlin系列Lambda表示式完全解析

簡述: 今天帶來的Kotlin淺談系列的第六彈, 一起來聊下Kotlin中的lambda表示式。lambda表示式應該都不陌生,在Java8中引入的一個很重要的特性,將開發者從原來繁瑣的語法中解放出來,可是很遺憾的是隻有Java8版本才能使用。而Kotlin則彌

Kotlin系列Lambda表示式(1)

今天開始後續的幾篇Kotlin的文章會介紹Kotlin中Lambda表示式相關的內容。 什麼是Lambda表示式 在Java8中引入了Lambda表示式,這是最令Java開發者激動和期待的一個功能。那究竟什麼是Lambda表示式呢? Lambd

Kotlin系列Lambda表示式(2)

上一篇文章講到了最基本的Lambda表示式,今天這篇文章繼續講Lambda表示式中的在作用域中訪問變數。 Java中的內部類訪問變數 當我們在函式內部使用匿名內部類時,我們可以在匿名內部類內使用函式的引數和函式內的區域性變數。當我們在使用Lamb

Kotlin系列命名引數和預設引數

今天一起來看看Kotlin的命名引數和預設引數。 如果你學過Python,那你對這兩個概念一定不陌生,那我們今天就來學習一波Kotlin中的預設引數和命名引數。 遇到的問題 為了說明命名引數和預設引數出現的必要性,我們先丟擲一個問題,如何打印出

Kotlin系列迭代集合與map

今天來學習一下Kotlin中如何迭代集合和map。 還是以往的慣例,先說說Java中的方式,在對比看看Kotlin中的方式。 Java中迭代集合和map 這個屬於Java中的基礎知識,這裡貼一下程式碼,方便後面與Kotlin對比。 Java程

Kotlin系列Lambda表示式(3)

今天一起來看看Kotlin中與Lambda相關的成員引用的內容。 定義 先說說什麼是成員引用,這裡的引用指的就是變數引用,就相當於Java中的引用概念。成員的概念這裡包含了成員變數和成員方法。這都是很官方的的說法。說白了,就是類裡面的變數和函式。

Kotlin系列集合和函式式API完全解析-上篇

簡述: 今天帶來的是Kotlin淺談系列的第八講,這講我們一起來聊聊Kotlin這門語言對函數語言程式設計的支援。我們都知道在kotlin這門語言中函式榮升成為了一等公民,所以在支援函數語言程式設計的方面,Kotlin這門語言也是非常給力的,並且在Kotlin中

Kotlin系列主構造方法和初始化語句塊

前面我們已經說過類和介面的知識點,今天來看看Kotlin中的主構造方法和初始化語句塊。 我們知道在Java中也存在構造方法的概念,也有初始化塊的概念。所以今天還是拿Kotlin和Java進行對比學習。 Java中的構造方法和初始化塊 在Java

SQL執行異常系列——統計信息不準

_id wid ora dbms dbm predicate 計算 tput 圖片 作為一線的dba,經常會遇到批量業務或聯機業務sql中統計信息不準導致的執行計劃異常的問題。雖較為常見,但還是記錄一下,作為SQL執行異常專題的開篇一章。要了解執行計劃,首先要理解統計信息,

SQL執行異常系列——隱式轉換

隱式 刷新 from cost exec ndt lte rownum varchar SQL> select object_id,CREATED from dba_objects where rownum < 10; OBJECT_ID CREATED

別扯那些沒用的系列:Java異常

引子 先來一起看看下面的程式碼: package com.huangzx.Exception; /** * @author huangzx * @date 2018/11/27 */ public class ExceptionTypeTest { public class Exceptio

SpringMVC學習系列(10) 異常處理

在專案中如何處理出現的異常,在每個可能出現異常的地方都寫程式碼捕捉異常?這顯然是不合理的,當專案越來越大是也是不可維護的。那麼如何保證我們處理異常的程式碼精簡且便於維護呢?這就是本篇要講的內容—>異常處理。 在Spring MVC中我們可以通過以下2中途徑來對異常進行集中處理: 一.繼承Handle