为什么猫王不应该访问Java
最近,我參與了一個關于Java的Optional類型系統的漫長的Twitter討論 ,該系統區分可空類型和非可空類型以及Elvis運算符 ,該運算符允許選擇空值安全的成員。 后者被認為是簡潔的null處理的殺手級功能,對此我強烈不同意。
我對此的看法是,如果沒有允許每個類型都不能為空的類型系統(Java不久將不會發生這種情況),Elvis運算符將不利于正確性和可讀性。
讓我解釋一下原因。
零的癥結
null的問題在于它沒有說明為什么缺少值
我以前已經寫過這個 。 null的問題不在于它會導致異常-只是一種癥狀。 null的問題在于它沒有說明為什么缺少該值。 是否嘗試過并且失敗了(例如連接到數據庫),但是由于某種原因,執行仍在繼續? 是否有許多值(可能是一對?),其中只能出現一個? 值是否像非強制性的用戶輸入一樣是可選的? 或者,最后,這是一個實際的實現錯誤,并且該值真的應該永遠不會丟失嗎?
錯誤的代碼將所有這些情況映射到同一件事:null。 因此,當NullPointerException或其他與缺失值相關的不良行為(“為什么此字段為空?”,“為什么搜索找不到該東西?”)彈出時,解決該問題的第一步是什么? 找出為什么缺少該值以及該值是否正確或實現錯誤。 實際上,回答該問題通常是解決方案的90%!
但是,這樣做非常困難,因為null可以隱藏在任何引用類型中,并且除非進行了嚴格的檢查(例如在構造函數和方法參數上使用Objects :: requireNonNull),否則它很容易在整個代碼庫中擴散。 因此,在回答為什么null在引起問題的地方出現之前,有必要先將其跟蹤到其來源,這在一個足夠復雜的系統中可能會花費很多時間。
因此,null的根本問題不是它引起的不當行為,而是將各種不同的關注點混為一個單一的,特別是偷偷摸摸且容易出錯的概念。
由Kevin Dooley在CC-BY 2.0下發布
貓王進入大樓
我最近與Kotlin一起玩耍,對空值處理感到驚訝,就像我以為我會從閱讀它開始一樣。 它不是唯一以這種方式執行的語言,而是我實際使用的語言,因此我以它為例。 但這僅僅是:一個例子。 這不是“ Kotlin比Java更好”的說法,而是“看看其他類型系統如何處理此問題”的闡述。
(如果您想進一步了解Kotlin的類型系統,我強烈建議您進行全面介紹 。)
無論如何,在這種類型的系統中,默認引用是不可為空的,并且編譯器確保不會發生任何意外。 字符串始終是字符串,而不是“字符串或null”。
// declare a variable of non-nullable type `User` val user : User = ... // call properties (if you don't know the syntax, // just assume these were public fields) val userStreet : String = user.address.street // if neither `address` not `street` return a nullable type, // `userStreet` can never be null; // if they would, the code would not compile because `userStreet` // is of the non-nullable type `String`當然,事情可能會丟失,并且可以通過追加使每種類型都為空。 對它。 從這一點開始,由于空引用,成員訪問(例如調用方法)存在失敗的風險。 令人敬畏的是,編譯器意識到了風險,并迫使您正確地處理風險(或者大打折扣,以克服抱怨)。 做到這一點的一種方法是什么? 貓王操作員!
Elvis,寫為?,區分成員所引用的引用是否為空。 如果為null,則不調用該成員,整個表達式的計算結果為null。 如果存在,則按預期方式調用該成員。
// declare a variable of the nullable type `User` val user : User? = ... // use Elvis to navigate properties null-safely< val userStreet : String? = user?.address?.street // if `user` is null, so is `userStreet`; // `address` and `street` might return nullable types在了解可空性的類型系統中,貓王是一種很棒的機制! 使用它,您可以表示自己知道值可能會丟失,并接受此結果作為調用結果。
同時,編譯器將強制您在可能為空的引用上使用它,從而防止意外的異常。 此外,它將強行將丑陋的nullability-property傳播給您將結果分配給的變量。 這迫使您隨身攜帶可能為null值的復雜性,并且有激勵您盡早擺脫它。
為什么這在Java中不起作用?
貓王只適用于非空類型
因此,如果我在Kotlin中非常喜歡Elvis,為什么不希望在Java中看到它? 因為貓王只能與區分可空類型和不可空類型的類型系統一起使用! 否則,它的作用與預期相反,并且使null問題變得更加棘手。
想一想:通過在null上調用成員可以得到NPE。 最簡單的事情是什么? 擠在那里的問號,并完成它!
那是對的嗎? Null不會告訴您是否允許丟失值,那么誰知道呢? 它會對調用或被調用代碼產生負面影響嗎? 好吧,編譯器無法告訴您該代碼是否可以處理null,那么又有人知道嗎?
像Kotlin的類型系統可以回答這兩個問題,而Java會讓您猜測。 正確的選擇是調查,這需要付出努力。 錯誤的選擇是只擴散null。 如果第二種選擇比今天簡單得多,您認為會發生什么? 您是否希望看到或多或少缺少值的問題? 您是否期望從null引用的源到導致問題變得更長或更短的路徑?
貓王讓錯誤的選擇變得容易
好的語言和好的API使正確的選擇變得容易。 良好的靜態類型系統中設計良好的類型可以排除運行時不應發生的情況。 這兩個帳戶上的Java貓王都將失敗。 與其要求一種更簡單的方法來處理null,不如最好從代碼庫或至少每種類型的public API中 消除它 。
一言以蔽之
Twitter上的大多數討論實際上都是圍繞Optional但在這里我不再重復,因為那是另一篇文章( 我已經寫過一遍, 實際上是兩次 )。 相反,我想強調一個特定的論點并將其置于貓王的語境中。
有人反復指出,這是Optional的弱點,它很容易被誤操作,使用不謹慎是一種可能甚至是普遍的情況。 就個人而言,我還沒有那個問題,但這聽起來很合理。 我認為可以通過適度的努力(肯定比正確的空值處理更容易)來學習處理Optional但是除非發生這種情況,否則我會明白濫用它會導致代碼庫變糟。
但是對于那些有這種想法的人,我想提出一個問題:您到底認為貓王的情況不會這么糟嗎? 正如我在上文中指出的那樣,這使可怕的選擇變得非常簡單! 可以說比Optional所能做到的更多。
摘要
缺乏必要的邪惡觀念。 編碼為null不好。 擴散可怕。
如果Java有一個類型系統可以幫助處理null并激勵人們遠離它,那么貓王會很棒。 ,不是。 因此,更容易在代碼庫中散布null而不是為丟失的值創建適當的設計,從而使針向錯誤的方向移動。
最后,打個招呼:如果您已經讀完所有這些,并且仍然想要Elvis,因為它會使您的生活變得更加輕松 ,那么您的API可能設計不當,因為它們過度使用了null。 在那種情況下,您渴望接觸Elvis的愿望正是我認為Java不應該擁有它的原因。
翻譯自: https://www.javacodegeeks.com/2017/02/elvis-not-visit-java.html
總結
以上是生活随笔為你收集整理的为什么猫王不应该访问Java的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (boot linux)
- 下一篇: 济南货车备案系统(济南货车备案)