成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

淺談Kotlin的Checked Exception機(jī)制

開發(fā) 后端
這門語言從一開始的無人問津,到后來成為Android開發(fā)的一級語言,再到后來Google官宣的Kotlin First。Kotlin正在被越來越多的開發(fā)者接受和認(rèn)可。

[[344629]]

現(xiàn)在使用Kotlin的Android開發(fā)者已經(jīng)越來越多了。

這門語言從一開始的無人問津,到后來成為Android開發(fā)的一級語言,再到后來Google官宣的Kotlin First。Kotlin正在被越來越多的開發(fā)者接受和認(rèn)可。

許多學(xué)習(xí)Kotlin的開發(fā)者之前都是學(xué)習(xí)過Java的,并且本身Kotlin就是一款基于JVM語言,因此不可避免地需要經(jīng)常和Java進(jìn)行比較。

Kotlin的諸多特性,在熟悉Java的開發(fā)者看來,有些人很喜歡,有些人不喜歡。但即使是不喜歡的那些人,一旦用熟了Kotlin進(jìn)行程序開發(fā)之后,也難逃真香定律。

今天我想跟大家聊一聊的話題,是Kotlin在早期的時候爭議比較大的一個特性:Checked Exception機(jī)制。

由于Kotlin取消了Checked Exception,這在很多Java開發(fā)者看來是完全不可接受的,可能也是許多Java支持者拒絕使用Kotlin的原因。但目前Kotlin已經(jīng)被Google轉(zhuǎn)正兩年多了,開發(fā)了成千上萬的Android應(yīng)用。你會發(fā)現(xiàn),即使沒有Checked Exception,Kotlin編寫出的程序也并沒有出現(xiàn)比Java更多的問題,因此編程語言中對于Checked Exception的必要性可能并沒有許多人想象中的那么高。

當(dāng)然,本篇文章中我并不能給出一個結(jié)論來證明誰對誰錯,更多的是跟大家談一談我自己的觀點(diǎn)和個人心得,另外引用一些大佬的權(quán)威觀點(diǎn)。

另外,這個問題永遠(yuǎn)是沒有正確答案的,因?yàn)槭澜缟蠜]有最好的編程語言(PHP除外)。每個編程語言選擇不同的處理方式都有著自己的一套理論和邏輯,所以與其去爭論Java中的Checked Exception機(jī)制是不是多余的,不如去論證Kotlin中沒有Checked Exception機(jī)制為什么是合理的。

那么,我們首先從什么是Checked Exception開始說起。

/ 什么是Checked Exception? /

Checked Exception,簡稱CE。它是編程語言為了保證程序能夠更好的處理和捕獲異常而引入的一種機(jī)制。

具體而言,就是當(dāng)一個方法調(diào)用了另外一個可能會拋出異常的接口時,要么將這個異常進(jìn)行捕獲,要么將這個異常拋出,交給上一層進(jìn)行捕獲。

熟悉Java語言的朋友對這一機(jī)制一定不會陌生,因?yàn)槲覀儙缀趺刻於荚谶@個機(jī)制的影響下編寫程序。

觀察如下代碼:

  1. public void readFromFile(File file) { 
  2.     FileInputStream in = null
  3.     BufferedReader reader = null
  4.     StringBuilder content = new StringBuilder(); 
  5.     try { 
  6.         in = new FileInputStream(file); 
  7.         reader = new BufferedReader(new InputStreamReader(in)); 
  8.         String line = ""
  9.         while ((line = reader.readLine()) != null) { 
  10.             content.append(line); 
  11.         } 
  12.     } catch (IOException e) { 
  13.         e.printStackTrace(); 
  14.     } finally { 
  15.         if (reader != null) { 
  16.             try { 
  17.                 reader.close(); 
  18.             } catch (IOException e) { 
  19.                 e.printStackTrace(); 
  20.             } 
  21.         } 
  22.     } 

這段代碼每位Java程序員應(yīng)該都非常熟悉,這是一段Java文件流操作的代碼。

我們在進(jìn)行文件流操作時有各種各樣潛在的異常可能會發(fā)生,因此這些異常必須被捕獲或者拋出,否則程序?qū)o法編譯通過,這就是Java的Checked Exception機(jī)制。

有了Checked Exception,就可以保證我們的程序不會存在一些隱藏很深的潛在異常,不然的話,這些異常會像定時炸彈一樣,隨時可能會引爆我們的程序。

由此看來,Checked Exception是一種非常有必要的機(jī)制。

/ 為什么Kotlin中沒有CE? /

Kotlin中是沒有Checked Exception機(jī)制的,這意味著我們使用Kotlin進(jìn)行上述文件流操作時,即使不捕獲或者拋出異常,也可以正常編譯通過。

熟悉Java的開發(fā)者們是不是覺得這樣嚴(yán)重沒有安全感?

那么我們就來嘗試分析和思考一下,為什么Kotlin中沒有Checked Exception。

我在學(xué)習(xí)Kotlin時,發(fā)現(xiàn)這門語言在很多設(shè)計(jì)方面都參考了一些業(yè)內(nèi)的最佳編程實(shí)踐。

舉個例子,《Effective Java》這本書中有提到過,如果一個類并非是專門為繼承而設(shè)計(jì)的,那么我們就應(yīng)該將它聲明成final,使其不可被繼承。

而在Kotlin當(dāng)中,一個類默認(rèn)就是不可被繼承的,除非我們主動將它聲明成open。

類似的例子還有很多很多。

因此,Kotlin取消Checked Exception也肯定不是隨隨便便拍腦瓜決定的,而是有很多的理論依據(jù)為其支持。

比如說,《Thinking in Java》的作者 Bruce Eckel就曾經(jīng)公開表示,Java語言中的Checked Exception是一個錯誤的決定,Java應(yīng)該移除它。C#之父Anders Hejlsberg也認(rèn)同這個觀點(diǎn),因此C#中是沒有Checked Exception的。

那么我們大多數(shù)Java開發(fā)者都認(rèn)為非常有必要的Checked Exception機(jī)制到底存在什么問題呢?

這些大佬們例舉了很多方面的原因,但是我個人認(rèn)為最主要的原因其實(shí)就是一個:麻煩。

Checked Exception機(jī)制雖然提升了編程語言的安全性,但是有時卻讓我們在書寫代碼時相當(dāng)抓狂。

由于Checked Exception機(jī)制的存在,對于一些可能發(fā)生潛在異常的代碼,我們必須要對其進(jìn)行處理才行。處理方式只有兩種:要么使用try catch代碼塊將異常捕獲住,要么使用throws關(guān)鍵字將異常拋出。

以剛才的文件流操作舉例,我們使用了兩次try catch代碼塊來進(jìn)行潛在的異常捕獲,但其實(shí)更多只是為了能讓編譯器滿意:

  1. public void readFromFile(File file) { 
  2.     BufferedReader reader = null
  3.     try { 
  4.         ... 
  5.     } catch (IOException e) { 
  6.         e.printStackTrace(); 
  7.     } finally { 
  8.         if (reader != null) { 
  9.             try { 
  10.                 reader.close(); 
  11.             } catch (IOException e) { 
  12.                 e.printStackTrace(); 
  13.             } 
  14.         } 
  15.     } 

這段代碼在Java當(dāng)中是最標(biāo)準(zhǔn)和規(guī)范的寫法,然而你會發(fā)現(xiàn),我們幾乎沒有人能在catch中寫出什么有意義的邏輯處理,通常都只是打印一下異常信息,告知流發(fā)生異常了。那么流發(fā)生異常應(yīng)該怎么辦呢?沒人知道應(yīng)該怎么辦,理論上流應(yīng)該總是能正常工作的。

思考一下,是不是你在close文件流時所加的try catch都只是為了能夠讓編譯通過而已?你有在close的異常捕獲中進(jìn)行過什么有意義的邏輯處理嗎?

而Checked Exception機(jī)制的存在強(qiáng)制要求我們對這些未捕獲的異常進(jìn)行處理,即使我們明確不想對它進(jìn)行處理都不可以。

這種機(jī)制的設(shè)計(jì)思路本身是好的,但是卻也間接造就了很多填鴨式的代碼,只是為了滿足編譯器去編程,導(dǎo)致編寫了很多無意義的try catch語句,讓項(xiàng)目代碼看來得變得更加臃腫。

那么如果我們選擇不對異常進(jìn)行捕獲,而是將異常向上拋出呢?事實(shí)證明,這可能也并不是什么特別好的主意。

絕大多數(shù)Java程序員應(yīng)該都使用過反射的API,編寫反射代碼時有一點(diǎn)特別討厭,就是它的API會拋出一大堆的異常:

  1. Object reflect(Object object, String className, String methodName, Object[] parameters, Class<?>[] parameterTypes) 
  2.         throws SecurityException, IllegalArgumentException,  
  3.         IllegalAccessException, InvocationTargetException,  
  4.         NoSuchMethodException, ClassNotFoundException { 
  5.     Class<?> objectClass = Class.forName(className); 
  6.     Method method = objectClass.getMethod(methodName, parameterTypes); 
  7.     return method.invoke(object, parameters); 

這里我只是編寫了一段最簡單的反射代碼,竟然有6個異常要等著我去處理。其中每個異常代表什么意思我也沒能完全搞明白,與其我自己去寫一大堆的try catch代碼,還不如直接將所有異常都拋出到上一層得了,這樣代碼看起來還能清爽一點(diǎn)。

你是這么想的,上一層的人也是這么想的,更過分的是,他可能還會在你拋出異常的基礎(chǔ)之上,再增加一點(diǎn)其他的異常繼續(xù)往上拋出。

根據(jù)我查閱到的資料,有些項(xiàng)目經(jīng)過這樣的層層累加之后,調(diào)用一個接口甚至需要捕獲80多個異常。想必調(diào)用這個接口的人心里一定在罵娘吧。你覺得在這種情況下,他還能耐心地對每一種異常類型都細(xì)心進(jìn)行處理嗎?絕對不可能,大概率可能他只會catch一個頂層的Exception,把所有異常都囊括進(jìn)去,從而徹底地讓Checked Exception機(jī)制失去意義。又或者,他可能會在當(dāng)前異常拋出鏈上再加一把火,為拋出100個異常做出貢獻(xiàn)。。。

最終我們可以看出,Java的Checked Exception機(jī)制,本身的設(shè)計(jì)初衷確實(shí)是好的,而且是先進(jìn)的,但是卻對程序員有著較高的編碼規(guī)范要求。每一層方法的設(shè)計(jì)者都應(yīng)該能清楚地辨別哪些異常是應(yīng)該自己內(nèi)部捕獲的,哪些異常是應(yīng)該向上拋出的,從而讓整個方法調(diào)用棧的異常鏈都在一個合理和可控的范圍內(nèi)。

然而比較遺憾的現(xiàn)實(shí)是,絕大多數(shù)的程序員其實(shí)都是做不到這一點(diǎn)的,濫用和惰性使用CE機(jī)制的情況廣泛存在,完全達(dá)不到Java本身設(shè)計(jì)這個機(jī)制所預(yù)期的效果,這也是Kotlin取消Checked Exception的原因。

/ 沒有CE不會出現(xiàn)問題嗎? /

許多Java程序員會比較擔(dān)心這一點(diǎn),Kotlin取消了Checked Exception機(jī)制,這樣不會導(dǎo)致我的程序變得很危險(xiǎn)嗎?每當(dāng)我調(diào)用一個方法時,都完全不知道這個方法可能會拋出什么異常。

首先這個問題在開頭已經(jīng)給出了答案,經(jīng)過兩年多的實(shí)踐發(fā)現(xiàn),即使沒有Checked Exception,Kotlin開發(fā)出的程序也并沒有比Java開發(fā)的程序出現(xiàn)更多的異常。恰恰相反,Kotlin程序反倒是減少了很多異常,因?yàn)镵otlin增加了編譯期處理空指針異常的功能(空指針在各類語言的崩潰率排行榜中都一直排在第一位)。

那么至于為什么取消Checked Exception并不會成為導(dǎo)致程序出現(xiàn)更多異常的原因,我想分成以下幾個點(diǎn)討論。

第一,Kotlin并沒有阻止你去捕獲潛在的異常,只是不強(qiáng)制要求你去捕獲而已。

經(jīng)驗(yàn)豐富的程序員在編寫程序時,哪些地方最有可能發(fā)生異常其實(shí)大多是心中有數(shù)的。比如我正在編寫網(wǎng)絡(luò)請求代碼,由于網(wǎng)絡(luò)存在不穩(wěn)定性,請求失敗是極有可能發(fā)生的事情,所以即使沒有Checked Exception,大多數(shù)程序員也都知道應(yīng)該在這里加上一個try catch,防止因?yàn)榫W(wǎng)絡(luò)請求失敗導(dǎo)致程序崩潰。

另外,當(dāng)你不確定調(diào)用一個方法會不會有潛在的異常拋出時,你永遠(yuǎn)可以通過打開這個方法,觀察它的拋出聲明來進(jìn)行確定。不管你有沒有這個類的源碼都可以看到它的每個方法拋出了哪些異常:

  1. public class FileInputStream extends InputStream { 
  2.  
  3.     public FileInputStream(File file) throws FileNotFoundException { 
  4.         throw new RuntimeException("Stub!"); 
  5.     } 
  6.  
  7.     public int read(byte[] b, int offint len) throws IOException { 
  8.         throw new RuntimeException("Stub!"); 
  9.     } 
  10.  
  11.     public void close() throws IOException { 
  12.         throw new RuntimeException("Stub!"); 
  13.     } 
  14.     ... 

然后當(dāng)你覺得需要對這個異常進(jìn)行捕獲時,再對它進(jìn)行捕獲即可,相當(dāng)于你仍然可以按照之前在Java中捕獲異常的方式去編寫Kotlin代碼,只是沒有了強(qiáng)制的要求,你可以自由選擇要不要進(jìn)行捕獲和拋出。

第二,絕大多數(shù)的方法其實(shí)都是沒有拋出異常的。

這是一個事實(shí),不然你絕對不會愛上Checked Exception機(jī)制,而是會天天咒罵它。

試想一下,假如你編寫的每一行代碼,調(diào)用的每一個方法,都必須要對它try catch捕獲一下才行,你是不是想摔鍵盤的心都有了?

我說的這種情況在Java中真的有一個非常典型的例子,就是Thread.sleep()方法。由于Thread.sleep()方法會拋出一個InterruptedException,所以每次我們調(diào)用這個方法時,都必須要用try catch捕獲一下:

  1. public class Main { 
  2.  
  3.     public void test() { 
  4.         // do something before 
  5.         try { 
  6.             Thread.sleep(1000); 
  7.         } catch (InterruptedException e) { 
  8.             e.printStackTrace(); 
  9.         } 
  10.         // do something after 
  11.     } 
  12.  

這也是我極其不喜歡這個方法的原因,用起來就是一個字:煩。

事實(shí)上,可能絕大多數(shù)Java程序員甚至都不知道為什么要捕獲這個異常,只知道編譯器提醒我必須捕獲。

之所以我們在調(diào)用Thread.sleep()方法時需要捕獲InterruptedException,是因?yàn)槿绻诋?dāng)前線程睡眠的過程中,我們在另外一個線程對中這個睡眠中的線程進(jìn)行中斷(調(diào)用thrad.interrupt()方法),那么sleep()方法會結(jié)束休眠,并拋出一個InterruptedException。這種操作是非常少見的,但是由于Checked Exception的存在,我們每個人都需要為這一個少見的操作買單:即每次調(diào)用Thread.sleep()方法時,都要寫一段長長的try catch代碼。

而到了Kotlin當(dāng)中,你會不再討厭使用Thread.sleep()方法,因?yàn)闆]有了Checked Exception,代碼也變得清爽了:

  1. class Main { 
  2.  
  3.     fun test() { 
  4.         // do something before 
  5.         Thread.sleep(1000) 
  6.         // do something after 
  7.     } 
  8.  

第三,擁有Checked Exception的Java也并不是那么安全。

有些人認(rèn)為,Java中擁有Checked Exception機(jī)制,調(diào)用的每個方法你都會感到放心,因?yàn)橹浪鼤伋鍪裁串惓!6鴽]有Checked Exception的話,調(diào)用任何方法心里都感覺沒底。

那么這種說法有道理嗎?顯然這不是真的。不然,你的Java程序應(yīng)該永遠(yuǎn)都不會崩潰才對。

事實(shí)上,Java將所有的異常類型分成了兩類:受檢查異常和不受檢查異常。只有受檢查異常才會受到Checked Exception機(jī)制的約束,不受檢查異常是不會強(qiáng)制要求你對異常進(jìn)行捕獲或拋出的。

比如說,像NullPointerException、ArrayIndexOutOfBoundsException、IllegalArgumentException這些都是不受檢查的異常,所以你調(diào)用的方法中即使存在空指針、數(shù)組越界等異常風(fēng)險(xiǎn),Checked Exception機(jī)制也并不會要求你進(jìn)行捕獲或拋出。

由此可見,即使Java擁有Checked Exception機(jī)制,也并不能向你保證你調(diào)用的每個方法都是安全的,而且我認(rèn)為空指針和數(shù)組越界等異常要遠(yuǎn)比InterruptedException之類的異常更加常見,但Java并沒有對此進(jìn)行保護(hù)。

至于Java是如何劃分哪些異常屬于受檢查異常,哪些屬于不受檢查異常,這個我也不太清楚。Java的設(shè)計(jì)團(tuán)隊(duì)一定有自己的一套理論依據(jù),只不過這套理論依據(jù)看上去并沒有被其他語言的設(shè)計(jì)者所認(rèn)可。

因此,你大概可以理解成,Kotlin就是把異常類型進(jìn)一步進(jìn)行了簡化,將所有異常都?xì)w為了不受檢查異常,僅此而已。

/ 結(jié)論 /

所以,最終的結(jié)論是什么呢?

很遺憾,沒有結(jié)論。正如任何事物都有其多樣性一樣,關(guān)于Checked Exception這個問題上面,也沒有一個統(tǒng)一的定論。

Java擁有Checked Exception機(jī)制并不是錯誤的,Kotlin中取消Checked Exception機(jī)制也不是錯誤的。我想這大概就是你閱讀完本文之后能夠得出的結(jié)論吧。

 

但是,希望你自此往后,在使用Kotlin編程程序時,不要再為有沒有Checked Exception的問題所糾結(jié)了。

本文轉(zhuǎn)載自微信公眾號「郭霖」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系郭霖公眾號。

 

責(zé)任編輯:武曉燕 來源: 郭霖
相關(guān)推薦

2009-07-16 09:46:20

iBATIS Log機(jī)

2023-12-11 07:21:12

SPI機(jī)制插件

2019-08-15 10:17:16

Webpack運(yùn)行瀏覽器

2011-07-26 10:46:04

HTML 5

2011-03-10 15:22:08

訪問控制機(jī)制Java

2009-07-09 16:33:06

eclipse jvm

2017-05-15 13:40:20

瀏覽器http緩存機(jī)制

2009-07-24 17:22:22

CLR 4.0安全模型

2013-09-29 15:11:46

Linux運(yùn)維內(nèi)存管理

2017-04-26 14:15:35

瀏覽器緩存機(jī)制

2009-06-30 09:55:24

Spring運(yùn)作機(jī)制

2010-04-16 11:17:33

hints調(diào)整

2019-05-10 14:00:21

小程序運(yùn)行機(jī)制前端

2020-02-26 09:00:00

Chatbot架構(gòu)模型聊天機(jī)器人

2018-12-06 14:47:34

區(qū)塊鏈中介信任

2015-06-16 10:44:42

2018-12-26 16:30:09

SQL Server內(nèi)部運(yùn)行機(jī)制數(shù)據(jù)庫

2009-01-05 09:17:36

Java通信API集成

2009-06-15 10:20:47

WF 4.0 Beta跟蹤機(jī)制

2009-12-21 10:05:10

ASP.NET MVC
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 日韩在线免费 | 久久久成人免费视频 | 久久久一二三区 | www国产成人免费观看视频 | 久久久久国产一区二区三区四区 | 日韩一级在线 | 精品二区| 中文字幕成人 | 国产精品欧美一区二区三区不卡 | 中文字幕人成人 | 成人欧美一区二区三区在线播放 | 日韩一区二区三区在线视频 | 亚洲午夜精品 | 欧美日韩综合 | 精品一区av | 在线精品一区二区 | 超碰在线网站 | 成人免费网视频 | 国产夜恋视频在线观看 | 羞羞在线观看视频 | 国产亚洲一区二区三区在线观看 | 日韩有码一区 | 日韩另类视频 | 欧美v在线观看 | 国产美女在线观看 | 欧美一区二区三区视频在线观看 | 91玖玖| 日韩精品一区二区三区老鸭窝 | 欧美男人天堂 | 久久久久久国产精品 | 在线看一区二区 | 成人亚洲精品久久久久软件 | 亚洲激情视频在线 | 久草视频观看 | 成人在线a | 欧州一区二区三区 | 老牛影视av一区二区在线观看 | 国产成人综合网 | 成人av网站在线观看 | 欧美男人天堂 | 亚洲国产成人久久综合一区,久久久国产99 |