反编译扒皮kotlin系列(一)

写做本文的目的

kotlin虽然不是java的语法糖,但在做用上确实就是个语法糖,学起来虽然轻松,可是有些概念不常用容易埋坑, 多看看kotlin反编译之后的代码 能够加深对 语法糖的 理解。也能够避免用java的写法来写kotlin。熟悉了之后能够更轻松自如的写kotlin味道的kotlin代码。java

const val 与 val

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方法。

kotlin中的解构

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的语法糖,但在做用上确实是无限接近于语法糖的做用的

kotlin中神奇的扩展函数

fun main() {

    var a = "hello world"
    println(a.doubleToString())
}

fun String.doubleToString(): String {
    return this.toString() + "__" + this.toString()
}

复制代码

初学kotlin的都以为 扩展函数很神奇,好比上面的代码。 扩展了string的函数 增长一个doubleToString的函数, 函数的做用我就不写了,你们一看就懂。

如今来反编译看看 这究竟是咋实现的

嗯 愈来愈像语法糖了。

inline 函数

仍是上面的例子

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函数 可想而知 你调用的地方就会多出来很是多的代码。 代码膨胀的速度是飞快的。

kotlin支持 函数做为参数的真相

这个又是一个相似于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关键字,看看会发生什么,这里就不演示了

init函数

fun main() {

    var p1 = Persont()

}

class Persont constructor() {

    init {
        println("111")
    }

    init {
        println("222")
    }

}
复制代码

运行之后结果以下:

反编译看一看:

因此说这个地方的init函数 无非就是 当你在kotlin中使用了主构造器的时候 把你的init里面的代码 按照顺序放到构造函数里面,其余没啥。 为何要这么作? 固然是由于主构造器的写法没有方法体,因此须要这么写,仅此而已。

相关文章
相关标签/搜索