Kotlin最近風(fēng)頭正勁僚饭,作為一個(gè)去年就關(guān)注這門語言,并且向朋友安利這門語言的小司機(jī)終于揚(yáng)眉吐氣了一回胧砰,自己選擇沒有錯鳍鸵。
最近在一個(gè)Kotlin群里,看到大家在討論一個(gè)問題尉间,是關(guān)于 == 和 === 的問題偿乖,看官方文檔解釋的意思大概是這樣子的
兩個(gè)等號==
== 兩個(gè)等號意思與Java中的 equals 意思一樣,就比如
var a = "字符串"
print(a == "字符串")
這段代碼在Kotlin中打印出來值就是true
三個(gè)等號===
=== 三個(gè)等號的意思乌妒,則比較的是內(nèi)存地址:就比如:
var a = "字符串"
var b = a
var c = a
print(b === c)
那么打印出來的值就是true
有人問了這么一句話:為什么我用Int得到的結(jié)果好好像有點(diǎn)不對汹想??
我重現(xiàn)了這位兄弟的場景:
這是執(zhí)行代碼:
這是執(zhí)行結(jié)果:
看到這里可能大家就看出一點(diǎn)端倪了撤蚊,明明是兩個(gè)變量古掏,兩次初始化,兩個(gè)等號相等為true可以理解侦啸,但是三個(gè)等號為true是為什么呢槽唾?
然后群里又有人說,在類型后面加個(gè)問號就可以了光涂,就是聲明成可選值就是可以達(dá)到我們預(yù)期的結(jié)果
然后我又試了一遍:
很明顯庞萍,答案還是一樣的,為什么呢忘闻?明明把值聲明成可選值了啊钝计。
又有人說,我把值稍微調(diào)大一點(diǎn),結(jié)果就不一樣了私恬。
然后我再次試了一遍:
看到這里就覺得好奇怪了债沮,為啥?為什么不加問號兩個(gè)值地址相等本鸣?加了問號 值小的情況下 兩個(gè)地址相等疫衩,值大的情況下,兩個(gè)地址不等荣德?闷煤?Kotlin是不是煞筆啊涮瞻?鲤拿?是不是有問題啊饲宛?帶著疑問我們繼續(xù)往下看:
然后我使用kotlin插件自帶的一個(gè)工具皆愉,直接查看Kotlin編譯出的class文件,再由class文件反編譯出Java代碼艇抠,來進(jìn)一步分析:
我們先看不加問號的情況:
看來反編譯還是有點(diǎn)問題的幕庐,但是并不影響我們分析,我們看到我在截圖中標(biāo)記出來的部分家淤,原來kotlin在內(nèi)部當(dāng)不加問號的時(shí)候异剥,就是基本類型,而在Java中絮重,兩個(gè)基本類型進(jìn)行地址進(jìn)行比較冤寿,地址是一樣的,所以kotlin直接編譯成兩個(gè)等號的意思青伤。
我們看加了問號督怜,值小的情況:
看到這里可以看到有點(diǎn)不一樣了,我們重點(diǎn)看一下標(biāo)記出來的部分狠角,這個(gè)看名字的意思應(yīng)該就是 equals 的意思号杠。
我們再看加了問號,值大的情況:
總結(jié)
到了這里丰歌,我們其實(shí)應(yīng)該有一種想法了姨蟋。
其實(shí)當(dāng)你不聲明為?可選值的時(shí)候立帖,就當(dāng)成Java基本數(shù)據(jù)類型進(jìn)行比較
而Java基本數(shù)據(jù)類型比較的話眼溶,地址與值都是相等的,為了節(jié)省這個(gè)比較地址的開銷晓勇,
kotlin直接編譯成JVM執(zhí)行的 == 的意思堂飞,
而當(dāng)你加了問號灌旧,聲明為可選值的時(shí)候,
意思就是可以為null酝静,也就是說节榜,就必須編譯為 Integer 只有integer才是既可以有數(shù)值羡玛,又可以為 null 别智。
integer包裝類的話,就是對象了稼稿,那么對象與對象進(jìn)行比較的話薄榛,地址是會不一樣的,那么為什么在值小的時(shí)候相等让歼,值大的時(shí)候不相等呢敞恋?
這個(gè)可能就與JVM的機(jī)制有關(guān)系了,【據(jù)說在JVM里面有一個(gè)常量池谋右,如果是這個(gè)值存在于這個(gè)常量池里硬猫,那么jvm會直接拿常量池里的對象進(jìn)行替換。所以你值小的時(shí)候得到的結(jié)果是相等的】改执。真的只是據(jù)說啸蜜,因?yàn)槲乙膊恢肋@句話是真的假的。有知道的請告訴我一下辈挂。我也學(xué)習(xí)學(xué)習(xí)衬横。
對Kotlin感興趣的可以加我的群:559259945
追加
群里老司機(jī)跟我說了,是JVM虛擬機(jī)的的優(yōu)化终蒂,范圍 -128 到 127之間有緩存