本文通過觀察 java ee 和 kotlin 的關系,探讨如何利用 kotlin 的運算符、可空性和 optional 來實作最大的效果。
将 java ee 應用轉換為 kotlin 始于架構的戰鬥,我們成功戰勝了所有阻礙和過時的标準。在這個過程中,代碼充斥着豐富而現代的 kotlin 特有的結構,變得簡潔而又不失安全。
如果還沒有讀這個系列的前面兩篇文章,可以看看:
kotlin and java ee: part one - from java to kotlin
kotlin and java ee: part two - having fun with plugins
先簡要回顧一下之前進行的改變,然後再補充一些最後的結果。
邊城
翻譯于 2周前
0人頂
頂 翻譯得不錯哦!
我們已經做了什麼
前兩個部分中的很多結構已經符合 kotlin 的慣例了。我們來看下 set 的定義:
由于 java 并不支援簡單地通過一些對象構造 set 或其它集合類型,是以我們需要用 arrays 類來建立 list (!),然後将其轉換為 set。在 kotlin 中代碼變成了:
private val classes = setof(kittenrestservice::class.java)
我們還把 java bean 轉換為 kotlin 資料類(data class),使代碼變得更簡短。我們去掉了所有 getter 和 setter,并自動獲得 equals()、hashcode() 和 tostring()。
因為有編譯器插件,我們可以“假冒”不可變對象而不需要無參數構造函數。
lateinit 關鍵字讓架構可以更友善地處理值的初始化,還可以避免不必要的空檢查:
再來看看我們還可以改進什麼。
null 還是 optional?
這是一個相當棘手的問題。kotlin 對可空值的支援已經很好了,尤其是在使用第三方庫的時候會有很大的幫助。問題是當你有機會進行選擇的時候你會選擇哪一個?下面是原來我們生成和使用 optional 的代碼:
慣用的 kotlin 解決方案會使用空值,像這樣:
可空值會出現在調用鍊的每個節點上,是以你必須使用問号來進行調用。它雖然解決了空值問題,但并不好看。
然而,如果傳回類型是 optional,而結果是 optional.empty,後面的所有單獨調用(monadic calls)都會被簡單的跳過,結果直接變成 optional.empty。對于我來說這是個很簡潔的解決方案,如果想從 java 調用 kotlin 代碼這也更安全, 對于 java 互操作,優先使用 optional 來處理可空值。
運算符!
find、add 和 delete 都是完全有效的方法名稱,但用運算符代替它們不是很好嗎?

我發現運算符不隻是更短,可讀性也更強,因為代碼不再是一大堆方法調用。但要小心使用大家都知道或了解的運算符,否則你會遇到和 scala 庫類似的大麻煩,然後就得有一個運算符表來解釋。在使用資料倉庫的情況下,類似 mutablemap 的接口工作良好。注意,我使用“指派加”(+=) 運算符來儲存一個實體,因為原來的集包含了已經擁有的元素,又另外增加了一個元素。
這是聲明:
你可能想保留原來的方法,同時使用運算符來對它們進行包裝,因為原來的方法可以傳回值,而某些運算符卻不能。其它可選用運算符的操作包括“remove” 和 “contains” 方法,因為它們可以用“指派減”(-=)和kotlin 的 in 運算符。剩下的請你充分發揮自己的想像。
結論
以符合使用習慣的方式書寫,目的是使代碼更具可讀性以及更安全,我希望展示的例子能夠成功地實作這一目标。 該系列僅顯示了幾種方法來改進 java 版本的代碼,同時使某些地方保持不變。一些值得探索的功能是:擴充函數,以及 if,when,try/catch 功能。去探索吧,找到對你有用的功能。
完整的代碼可以在這裡找到。