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里面的代码 按照顺序放到构造函数里面,其余没啥。 为何要这么作? 固然是由于主构造器的写法没有方法体,因此须要这么写,仅此而已。