before block
高阶函数
end block
这看不出啥区别,当需求发生变化,我想在回调方法中加个String类型的参数,该如何实现呢?
1.2 带参示例
// 定义接口
interface Consumer {
fun accept(way: String)
}
fun main() {
pay(Consumer {
println(“回调函数…it=$it”)
})
pay{
println(“高阶函数…it=$it”)
}
}
fun pay(block: Consumer) {
println(“before block”)
block.accept(“支付宝”)
println(“end block”)
}
// String 指的是方法参数
fun pay(block: (String) -> Unit) {
println(“before block”)
block(“支付宝”)
println(“end block”)
}
// Int 指的是block函数的返回值
fun pay2(block: (String) -> Int) {
println(“before block”)
block(“支付宝”)
println(“end block”)
}
-
如果是以回调的形式,得先创建一个接口,定义参数,如果后面参数变成2个,又得新建1个接口。
-
而
kt的高阶函数用起来更加灵活。
二 🌵内联函数
========
2.1 介绍
-
定义:方法名前面 加个
inline就是内联函数 -
作用:减少函数的调用来优化性能
-
使用场景:并不是每个函数前加一个 inline 就可以优化性能,如果某个方法的参数包含
高阶函数,那建议加上inline。典型的一个应用场景就是Kotlin的集合类。
filter 和 map 方法里的参数都是高阶函数,所以这2个方法加上 inline 关键字后,调用这2个方法时,会减少嵌套, 优化性能,见下面示例。

2.2 非内联函数
fun main() {
pay(Runnable {
println(“回调函数…”)
})
payNoInline{
println(“高阶函数…”)
}
}
fun pay(block: Runnable) {
println(“before block”)
block.run()
println(“end block”)
}
fun payNoInline(block: () -> Unit) {
println(“before block”)
block()
println(“end block”)
}
通过字节码反编译的相关Java代码如下:

-
发现高阶函数作为参数时和方法回调没什么区别,
-
并且方法参数中还新增加了额外的类
Function0和block.invoke()函数调用
《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享
开销。
2.3 🔥内联函数
fun main() {
pay(Runnable {
println(“回调函数…”)
})
payInline{
println(“高阶函数…”)
}
}
…
fun payInline(block: () -> Unit) {
println(“before block”)
block()
println(“end block”)
}
通过字节码反编译的相关Java代码如下:

-
当调用 payInline( 高阶函数) 时,会把 payInline()里面的方法体取过来并和当前高阶函数合成一个整体执行。
-
不会调用 payInline()方法,不会调用block.invoke(),执行效率提高了许多。
-
当函数里的某个参数为高阶函数时,建议您使用
inline修饰该函数。
三 🌷泛型
======
3.1 🔥reified 强烈推荐
- reified 是kt语言在泛型中独有的关键字,作用是把抽象的东西更加具体或真实,让泛型用起来更简单安全。
inline fun Activity.openAct() {
startActivity(Intent(this, T::class.java))
}
fun Activity.openAct(clazz: Class) {
startActivity(Intent(this, clazz))
}
fun main(){
// 启动Activity的方式1
openAct(MyAct::class.java)
// 启动Activity的方式2
openAct()
}
使用 reified时,必须和inline一起。再见 .class.java ,你好 reified
3.2 上界约束(out or extend)
-
java:
T extends Object -
kotlin:
T : Object和out : Object
指的是其类型必须是它的子类型或者它自己。out一般将泛型作为某个对象返回, 详情见下面 out协变讲解。
类的关系图如下:

open class People
open class Man : People()
class Man1 : Man()
class Man2 : Man()
class User
fun createUser(user4: User4){}
fun main()
var u = User() // 泛型可以是自己
var u1 = User() // 泛型可以是子类
// var u2 = User() // 编译错误
val c1 = createUser(User4(Man1()))
// val c2 = createUser(User4(People())) // 编译错误
}
3.3 下界约束(in or super)
-
java中是
? super Object -
kotlin中是
in Object
open class People
open class Man : People()
class Man1 : Man()
class Man2 : Man()
class User
fun main() {
var list: ArrayList?= ArrayList()
list.add(Man())
// 为什么可以添加进去呢?因为编译器会这么去存list.add((Man)Man1)
// 小转大是隐性的,大转小强转才需要手动加类型。
list.add(Man1())
// 那这里为什么又不能存 Man 的父类呢?
// 因为手动add()进去的数据都必须是绝对安全的(最低级父类:本身)才能通过。所以直接add父类也是不行的。
// list.add(People()) 编译错误
fun getMan(): ArrayList = ArrayList()
fun getMan1(): ArrayList = ArrayList()
fun getPeople(): ArrayList = ArrayList()
list = getMan()
// list = getMan1() 编译错误
list = getPeople()
}
3.4 类型限定(where)
interface Fly
class Man
class Man1 : Man, Fly
class Man2 : Man
// 限定传入的T只能是Man或其子类 并且实现了Fly接口
class User(var t:T) where T: Man, T:Fly
fun main() {
var u1 = User(Man1())
// var u2 = User(Man2()) // 编译报错,Man2没有实现Fly
}
