常見Kotlin高頻問題解惑

在筆者的Kotlin交流群里,不少同學反復遇到了一些相似的問題。這些問題大都比較基礎,但又容易產生誤解。因此,我決定寫一篇文章,整理群里同學遇到的一些問題

變量和常量的使用

在Kotlin語言中,我們使用var聲明變量,使用val聲明常量。由于來自Java語言中沒有區分常量變量的影響,一些同學對這兩個關鍵字的理解有問題。為了理解這兩個變量的區別,我們可以用兩個等式來說明一下:

var str: String = "abc"  => public String str = "abc"val str: String = "abc" => public final String str = "abc"
復制代碼

=>符號后面是對應的Java代碼,Java語言使用final關鍵字聲明常量。很明顯,使用明確的變量和常量聲明更有助于理解。

注:一些Java程序員很少使用final關鍵字,這說明這部分同學對于常量的使用不太理解。事實上,JVM中有一個常量池,如果發現常量池中存在該值就直接使用;反之,則創建并存入常量池。從這個層面來說,使用常量比使用變量效率更高。更重要的是,如果你聲明一個不會被改動的變量,使用final修飾將更準確,也更安全。

lateinit

其實,在使用Kotlin語言的這兩年里,我從來沒有用過這個關鍵詞。但剛剛接觸Kotlin語言的同學似乎很喜歡使用這個修飾符修飾變量。

這個關鍵詞是做什么的呢?這很有意思!

在Kotlin語言中,我們必須嚴格區分可選值和非可選值。而無論是可選值還是非可選值,在聲明的時候你都必須首先初始化。

那么,如果本身是一個非可選值,但在初始化的時候我們并不知道應該賦什么初始值。或者說,我們壓根就不想賦初始值,該怎么辦?lateinit就是用于解決這個問題的。

其實這個場景的確廣泛存在,比如這個變量是一個對象類型的數據。很明顯,給一個對象變量賦予一個初始值的意義不大。因此,你可以選擇使用lateinit修飾這個變量。可是,與此同時,你的災難也降臨了!

群里同學反饋多次的一個問題就是:提示變量沒有初始化。

其實,本身這個問題并不難,但難的是你要完全弄清楚使用lateinit的前提。如果你決定使用lateinit,你至少應該記住下面兩個規則:

  1. lateinit只能用于修飾非可選值。因此,必須確保你的這個變量在任何時候都不會被賦值為空。
  2. lateinit表示這個變量的初始化可能發生在任何時候。因此。使用lateinit之前,問一問自己。你是否非常清楚你一定會在使用這個變量之前將其進行初始化。

為了避免因為未初始化引起的異常問題,Kotlin語言為每一個lateini屬性實例提供了一個判斷是否已經初始化的屬性值isInitialized。因此,為了避免出現初始化問題,你最好判斷一下這個變量是否已經完成初始化:

private lateinit var dog: Dog
if (::dog.isInitialized) {....
}
復制代碼

非可選值中的空指針陷阱

部分同學喜歡這樣聲明數據類:

data class Ticket(var id: Long, var name: String ...) 
復制代碼

對于客戶端類應用,數據類通常對應后臺返回的一段Json字符串。那么,悲劇又誕生了!如果后臺沒有返回name字段,Json框架在進行數據解析的時候認為name為空值,嘗試將其賦值為空。不可預料地,臭名昭著的空指針異常又出現了。

因此,記住一個原則:除非你確定這個變量一定不會被賦值為空。否則,請盡量使用可選值。

可選值中的空指針陷阱

類似地,在可選值中也存在著空指針陷阱。而因為受到Java語言的影響,這個部分出現空指針異常的概率更高。看下面的例子:

var isRight: Boolean? = nullif (isRight!!) {...
}
復制代碼

對于上面的代碼,Kotlin將毫不留情地拋給你一個空指針異常。比Java空指針異常更溫柔的是,這個空指針異常的名稱叫做KotlinNullPointerException

因此,記住一個原則,如果使用可選值需要進行解包的時候。一定要確定這個可選值此刻是有值的。針對上面這個例子,更好的處理方式應該是這樣:

var isRight: Boolean? = nullif (isRight ?: false) {...
}
復制代碼

不要誤會,我沒有基本數據類型

Kotlin認為所謂的基本數據類型,所謂的拆包,封包是沒有意義的。因此,在Kotlin語言中所有的基本數據類型變量也是對象,擁有與變量一樣的行為。

所以,記住一個原則,從Java轉換到Kotlin,在使用基本數據類型變量的時候同樣需要注意合理地選擇可選值和非可選值,慎用lateinit。

雙冒號到底是個什么東西

雙冒號(::)操作符是Kotlin語言特有的操作符。它主要有以下幾個作用:

  1. 獲取KClass引用
  2. 獲取函數引用
  3. 獲取屬性引用
  4. 獲取構造函數引用

獲取KClass引用

這是很常用的表達式,不過通常用于獲取java的Class實例:

val javaClass = Person::class.java
復制代碼

注:這在Android開發中比較常用,通常用于獲取Activity的Java class實例。

獲取函數引用

在Kotlin語言中,你可以使用函數作為某個高階函數的參數。使用雙冒號操作符可以用于獲取具體的函數引用作為參數傳入目標函數:

fun cdn(x: Int): Boolean {return x >= 3
}fun filter(x: Int, condition: (x: Int)->Boolean): Boolean {return condition(x)
}filter(5, ::cdn)
復制代碼

獲取屬性引用

Kotlin類中每一個成員變量對應一個Property實例,使用雙冒號操作符可以用于獲取該屬性實例。在lateinit場景中,這很有用!

class Dog {var name: String? = null
}
// 注意:這里獲取的是Property實例,而非屬性本身
val property = Dog::nameval receiver = Dog()
println(property.get(receiver))
復制代碼

注:類對象變量本身并沒有isInitialized屬性,要判斷lateinit變量是否已經完成初始化,需要通過雙冒號獲取該變量對應的Property實例才能判斷。

獲取構造函數引用

雙冒號操作符也可以用于獲取某個對象的構造函數實例,具體的用法是:在類名稱前面使用雙冒號。看下面的例子:

class Dog {var name: String? = null
}val init = ::Dog
val dog = init()
println(dog.name)
復制代碼

注:該構造函數實例同樣可以作為參數傳入某個高階函數中。

PS:雙冒號操作符其實就是用于簡化Kotlin反射而創造的一種操作符。

簡單總結

你在日常使用Kotlin語言的過程中還有遇到其它問題嗎?如果有,請留言告訴我!

歡迎加入Kotlin交流群

如果你也喜歡Kotlin語言,歡迎加入我的Kotlin交流群: 329673958 ,一起來參與Kotlin語言的推廣工作。

編程,我們是認真的!

關注歐陽鋒工作室,與歐陽鋒同行!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/278109.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/278109.shtml
英文地址,請注明出處:http://en.pswp.cn/news/278109.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

關于神經網絡訓練的一些建議筆記

關于網絡訓練時的參考建議: 1.train loss不斷下降,test loss不斷下降,網絡正在學習 2.train loss不斷下降,test loss趨于不變,網絡過擬合,需要增大數據;減小網絡規模dropout;權重衰減…

Microsoft Teams的保留策略

Microsoft Teams保留策略現在可在Office 365安全性和合規性中心里進行配置 今天,我們很自豪地宣布,我們正在開始推出針對Microsoft Teams的保留策略。 推出預計將在未來幾周內完成。 通過此次發布,Teams管理員可以使用Office 365安全性和合規…

八年溯源,如何巧搭區塊鏈

虎嗅注:區塊鏈正在逐步商業化,但最大的挑戰是共識。 為什么這樣說?因為商品的溯源防偽業務在過去正是因為缺乏信任感而沒有得到普及,這是每個溯源從業者最大的感受。 在虎嗅虎跑團每兩周一次線上分享會上,溯源鏈創始人…

數字簽名過程及數字證書

數字簽名是什么? 作者:David Youd 翻譯:阮一峰 原文網址:http://www.youdzone.com/signature.html 1.鮑勃有兩把鑰匙,一把是公鑰,另一把是私鑰。 2.Bob把公鑰送給他的朋友們-Pat、Doug、Susan-- 每人一把…

Teams與OneDrive for Business和SharePoint的關系

作為一個相對看重個人信息安全與隱私的人,個人附件等資料在Microsoft Teams中的存儲方式、文件訪問權限、可見范圍問題引起了我的好奇。 眾所周知,Teams包含3大主要的模塊:單人聊天、團隊、會議。那下面讓我們一起來看一下,對這三…

hadoop學習筆記(二):centos7三節點安裝hadoop2.7.0

環境win7vamvare10centos7 一、新建三臺centos7 64位的虛擬機 master 192.168.137.100 root/123456 node1 192.168.137.101 root/123456 node2 192.168.137.102 root/123456 二、關閉三臺虛擬機的防火墻,在每臺虛擬機里面執行: systemctl sto…

index.html 的默認301或者302跳轉

index.html 的默認301或者302跳轉 <!DOCTYPE html> <html> <head> <title>Google</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> <script>window.locat…

在Microsoft Teams中的Visio協作

所有Team站點都帶有專用文件庫&#xff0c;用于存儲所有工作組的內容。 您現在可以從桌面或云存儲站點將Visio文件上載到此庫&#xff0c;例如&#xff0c;您所在Team的資產都集中在一個位置&#xff0c;供具有權限的任何人進行訪問。與其他存儲文件一樣&#xff0c;您可以直接…

用區塊鏈打擊假新聞 這可能是最2017年的一件事

據外媒報道&#xff0c;非營利性基金會PUBLIQ公布了一個基于區塊鏈打造的平臺。這是一個用于創建和分享原創新聞和媒體內容的平臺&#xff0c;它將在近期推出。據了解&#xff0c;PUBLIQ創建這一平臺則是希望能借用類似于比特幣一樣的系統來打擊假新聞。 通過創建一個受信任的經…

oo面向對象第一單元總結

oo第一次作業主要考察了多項式的求導&#xff0c;從簡單的冪函數求導到三角函數求導再到嵌套函數的求導&#xff0c;難度循序漸進&#xff0c;對我們對于面向對象的理解的要求也在一次一次提升。一行行代碼打下來&#xff0c;一夜夜熬過去&#xff0c;我也來到了這個短暫的停靠…

Microsoft Teams免費版本初體驗

Microsoft Teams推出有一段時間了&#xff0c;如果想要體驗Teams&#xff0c;必須需要有Office365的訂閱。最近微軟為了進一步推廣Teams&#xff0c;突然宣布Teams免費了。使用過Teams的讀者知道Teams是基于Office365賬號和組的&#xff0c;那它免費后&#xff0c;不使用Office…

JS:封裝函數判斷數據類型

思路 1 ).根據 typeof() 的返回值將數據分為2種情況 a.返回值為 string number boolean undefined function (直接返回 typeof() 的返回值) b.返回值為object 2 ).再將 typeof() 返回值為 object 的數據分為2種情況 a.null (直接返回自身) b.包裝類 對象 數組 (再進行細分) var…

強制禁用gitlab的雙因子認證:Two-Factor Authentication

&#xff08;一&#xff09;問題描述&#xff1a; 此博客解決如下問題&#xff1a;禁用gitlab的雙因子認證 禁用前&#xff0c;如圖&#xff08;此時&#xff0c;你在gitlab中什么也干不了&#xff09; &#xff08;二&#xff09;思路分析&#xff1a; 百度了很多方法&#xf…

如何將Outgoing Webhook部署到中國版Azure

在這篇文章中&#xff0c;我們主要來如何將Azure DevOps中的項目作為應用發布到中國版Azure的App Service中。 什么是Azure DevOps Azure DevOps, 原名為VSTS, 全稱是Visual Studio Team System&#xff0c;是由微軟開發的一套具有高生產力、高集成性、可擴展的生命周期開發工…

Google SRE 讀書筆記 扒一扒SRE用的那些工具

寫在前面 最近花了一點時間閱讀了《SRE Goolge運維解密》這本書&#xff0c;對于書的內容大家可以看看豆瓣上的介紹。總體而言&#xff0c;這本書是首次比較系統的披露Google內部SRE運作的一些指導思想、實踐以及相關的問題&#xff0c;對于我們運維乃至開發人員都有一定的借鑒…

第8章 java中的并發工具類

8.1 等待線程完成的CountDownLatch 作用&#xff1a;讓一個線程等待其余線程完成之后在繼續執行&#xff0c;如主線程等待開啟服務的子線程執行完畢后主線程繼續執行&#xff0c;類似于join。 轉載于:https://www.cnblogs.com/AshOfTime/p/10608910.html

Microsoft Teams的Meet Now功能

今天&#xff0c;我們宣布完成了Skype for Business to Teams路線圖中首次披露的幾項關鍵會議功能。當個人聯系&#xff0c;溝通和協作時&#xff0c;工作就自然而然的完成了&#xff0c;我們相信這些功能&#xff08;除了我們2月的公告之外&#xff09;使Microsoft Teams為所有…

深入 Adobe Reader 保護模式 —— 第一部分 —— 設計

原作者&#xff1a;Liz McQuarrie, Ashutosh Mehra, Suchit Mishra, Kyle Randolph, Ben Roger 譯者&#xff1a;lordVice 校對&#xff1a; StrokMitream 看雪翻譯小組 介紹 我是 Kyle Randolph&#xff0c; 和我一起的還有負責 Acrobat 系列產品的安全團隊&#xff0c; 這些產…

Java泛型主題討論

說明&#xff1a;在學習泛型這一知識點中&#xff0c;主要參考自《瘋狂Java講義》第7章P307-P330的泛型內容&#xff0c;因為是跳著閱讀&#xff0c;所以前面的一些名詞不是特別清楚&#xff0c;這里也做出適當備注&#xff0c;供自己識記與理解。 1.泛型 理解&#xff1a;說到…

初學Vue.js,從頭來過~

之前上課也學過vue.js&#xff0c;但是一遍過下來&#xff0c;實話&#xff0c;沒有記住什么&#xff0c;所以決定自己在對照著文檔過一遍&#xff0c;所以之后會弄一些基礎的東西&#xff0c;還請大神們莫噴~~~~今天先給平臺打一個預防針&#xff0c;Young C 要來啦~~ 吼吼&…