Kotlin的::语法和高阶函数遇坑记

大家都知道,Kotlin有高阶函数,每个函数的函数类型由函数的形参列表、->和返回值类型组成。比如:

fun pow(base : Int, expo : Int) : String {}
// 使用::将函数名称赋值给变量
var myfun : (Int, Int)->String = ::pow 

函数类型就像数据类型一样,既可用于定义变量,也可用作函数形参类型,还可作为函数的返回值类型,像C的函数指针。

最近在项目开发中遇到一个坑,简要的代码是这样的:

object A {
    data class Job(private val foo: WeakReference<(Int)->Unit>)
    private val queue = Queue<Job>()
    fun doWork() {
        // ...
        job = queue.get(0)
        job.get()?.invoke(1)
    }
    
    fun addJob(job: Job) {
        queue.add(job)
    }   
}

class B() {
    fun add(i : Int) {
    } 
    fun foo() {
        A.addJob(Job(WeakReference(::add)))
    }
}

A和B都在一个前台Activity C里,某个时刻会触发A的doWork方法,回调到B的add方法,这个就是背景。开发过程中发现job.get()拿出来的一直是个空,按理来说C拿着B,add函数又是在B里面,这个引用链应该是没问题的。后来把它编译成字节码后看了下,变成了类似下面这样:

class A {
    class Job{
        private final WeakReference<Function1<Int, Unit>> callback;
    }
    //...
}
class B {
    public void foo() {
        A.addJob(Job(WeakReference(new D(this))))
    }
}

class D{
    private B b;
    D(B b) {
        this.b = b
    }
    public void foo1(int i){
        b.add(i)
    }
}

传给WeakReference的竟然变成一个匿名对象,这个没人引用这个匿名对象,肯定马上就被回收了。

在这里插入图片描述

后来把B改成下面这样就好了:

class B() {
    private val add = { i: Int ->
        //...
    }
    fun foo() {
        A.addJob(Job(WeakReference(add)))
    }
}

看编译后的,这个时候传给WeakReference的就是一个成员变量了。
在这里插入图片描述
在这里插入图片描述
这个callback相当于是B的成员函数
对新的语法还是不够了解,才会遇到这个坑。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值