kotlin雖然不是java的語法糖,但在做用上確實就是個語法糖,學起來雖然輕鬆,可是有些概念不常用容易埋坑, 多看看kotlin反編譯之後的代碼 能夠加深對 語法糖的 理解。也能夠避免用java的寫法來寫kotlin。熟悉了之後能夠更輕鬆自如的寫kotlin味道的kotlin代碼。java
object MyObject {
const val t1 = 1
val t2 = 2
}
複製代碼
來看看反編譯之後的代碼es6
public final class MyObject {
public static final int t1 = 1;
private static final int t2 = 2;
public static final MyObject INSTANCE;
public final int getT2() {
return t2;
}
private MyObject() {
}
static {
MyObject var0 = new MyObject();
INSTANCE = var0;
t2 = 2;
}
}
複製代碼
從代碼中能夠看到 訪問t1 的時候 是直接經過 field來訪問 訪問t2 的時候 就是用的 方法了。bash
因此總結下區別:閉包
const val 是public的 val 是private的,訪問效率上 val 要低一些,const val 要高一些。 由於訪問val是經過方法,要有一次方法調用。而const val 則是直接訪問field 效率更高函數
實話說 這個設計我以爲是一個很是失敗的設計,都快和js同樣了。但既然kotlin這樣設計了 咱們仍是看看爲何這樣設計性能
fun main() {
var user1 = User3("wuyue", "t3")
var user2 = user1.copy()
println(user1 == user2)
println(user1 === user2)
}
data class User3(var username: String, var password: String?)
複製代碼
他的執行結果:ui
在java中顯然是沒有=== 這個操做符的。可是kotlin中。 上面的代碼 我直接解釋成this
== 在koltin中表明 對象中的field 是否相等。 === 表明引用是否相等。spa
來反編譯看看設計
看下copy函數作了啥
看到這應該能明白kotlin的 copy函數 其實就是從新new了一個對象 固然是淺拷貝。
==走的 就是下面這個函數
顯然這個eqauls 就是user3的equals了
看到這你應該就能明白kotlin中的 == 與 === 的區別是哪來的了。 同時也能夠知道 data class 這種寫法
會自動根據咱們設定的field來幫咱們生成equals方法。
package com.wuyue
data class Response(var code:Int,var message:String)
fun execute():Response{
val code=200
var message="ok"
return Response(code,message)
}
fun main()
{
val(code,message)= execute()
println(code)
println(message)
}
複製代碼
這個代碼相信不少人都看得懂, 看main函數裏 的第一行代碼 這樣的寫法其實和es6中的解構實際上是差很少的 也就是說 咱們能夠在一個函數調用中 返回多個值 ,這樣的寫法比咱們不停的get出來返回值 要高效的多。 可是注意了這裏和go語言中的函數多返回值是不同的。
咱們來看看kotlin中 是如何實現解構的
首先能夠看一下:
data class 的寫法 生成的bean代碼 中 是多了這2個函數的。
而後看看調用時的寫法
不用解釋了吧。。。因此看到這 你應該能夠理解這句話: kotlin雖然不是java的語法糖,但在做用上確實是無限接近於語法糖的做用的
fun main() {
var a = "hello world"
println(a.doubleToString())
}
fun String.doubleToString(): String {
return this.toString() + "__" + this.toString()
}
複製代碼
初學kotlin的都以爲 擴展函數很神奇,好比上面的代碼。 擴展了string的函數 增長一個doubleToString的函數, 函數的做用我就不寫了,你們一看就懂。
如今來反編譯看看 這究竟是咋實現的
嗯 愈來愈像語法糖了。
仍是上面的例子
inline fun String.doubleToString2(): String {
return this.toString() + "__" + this.toString()
}
fun main() {
var a = "hello world"
println(a.doubleToString())
println(a.doubleToString2())
}
fun String.doubleToString(): String {
return this.toString() + "__" + this.toString()
}
複製代碼
你看我新增了一個內聯函數,這東西幹啥的?傳說能提升性能?反編譯看一看
一眼就看出來,加上inline關鍵字的地方 在實際函數調用時 其實就是直接調用了inline函數體裏面的語句
而沒有直接調用函數自己,相對而言能夠節省一次函數調用。可是也就僅此而已了。 我的認爲少一次函數調用出棧入棧 其實並提升不了多少效率。
反而的這樣還會帶來代碼膨脹。假設你inline函數裏面語句很是多,那麼你若是在不少地方都調用了這個inline函數 可想而知 你調用的地方就會多出來很是多的代碼。 代碼膨脹的速度是飛快的。
這個又是一個相似於js的功能。咱們來看看kotlin實際是怎麼作的
class View {
interface OnClickListener {
fun onClick(view: View)
}
fun setOnClickListener(listener: (View) -> Unit) {
}
}
fun main() {
var view = View()
view.setOnClickListener {
onClick(view)
}
}
fun onClick(view: View) {
println("被點擊")
}
複製代碼
很像js的閉包了,java中就不能夠傳遞一個函數做爲一個參數,可是kotlin能夠, 那咱們看看是怎麼作的
首先反編譯能夠看出來 其實在定義的時候 仍是interface在起做用的。
咱們最終調用的時候 也能夠看出來 仍是遵循的java的規範 傳遞的是一個實際的對象。並非函數。
這裏你們有能夠試試 在回調函數這邊增長個inline關鍵字,看看會發生什麼,這裏就不演示了
fun main() {
var p1 = Persont()
}
class Persont constructor() {
init {
println("111")
}
init {
println("222")
}
}
複製代碼
運行之後結果以下:
反編譯看一看:
因此說這個地方的init函數 無非就是 當你在kotlin中使用了主構造器的時候 把你的init裏面的代碼 按照順序放到構造函數裏面,其餘沒啥。 爲何要這麼作? 固然是由於主構造器的寫法沒有方法體,因此須要這麼寫,僅此而已。