with
with 是将某个对象作为函数的参数,在函数块内可以通过 this 指代该对象。
//使用 with 之后,在 with 函数块内可以省略"content."
class AppPublisherAdapter : BaseAdapter<BoundAppInfoResponse.AppInfo>() {
override fun getLayoutId(viewType: Int): Int = R.layout.cell_app_publisher
override fun onBindViewHolderImpl(holder: BaseViewHolder, position: Int, content: BoundAppInfoResponse.AppInfo) {
with(content) {
holder.itemView.tv_game_name.text = name
if (is_bound) {
holder.itemView.tv_bound_user_name.text = bound_user_name
holder.itemView.tv_bound_user_name.setTextColor(context.color(R.color.color_bound_user_name))
} else {
holder.itemView.tv_bound_user_name.text = context.string(R.string.bind_on_account)
holder.itemView.tv_bound_user_name.setTextColor(context.color(R.color.color_bind_on_account))
}
holder.itemView.iv_game_icon.load(logo_url)
}
}
}
apply
apply 函数是指在函数块内可以通过 this 指代该对象,返回值为该对象自己。
@JvmStatic
fun main(args: Array<String>) {
val result ="Hello".apply {
println(this+" World")
this+" World" // apply 会返回该对象自己,所以 result 的值依然是“Hello”
}
println(result)
}
run
run 函数类似于 apply 函数,但是 run 函数返回的是最后一行的值。
@JvmStatic
fun main(args: Array<String>) {
val result ="Hello".run {
println(this+" World")
this + " World" // run 返回的是最后一行的值 Hello World
}
println(result)
}
let
let 函数把当前对象作为闭包的 it 参数,返回值是函数里面最后一行,或者指定 return。它看起来有点类似于 run 函数。
let 函数跟 run 函数的区别是:let 函数在函数内可以通过 it 指代该对象。
//可以在 obj 不为 null 的情况下执行 let 函数块的代码,从而避免了空指针异常的出现。
obj?.let {
....
}
also
also 是 Kotlin 1.1 新增的函数,类似于 apply 的功能。跟 apply 不同的是,also 在函数块内可以通过 it 指代该对象,返回值为该对象自己。
@JvmStatic
fun main(args: Array<String>) {
val result ="Hello".also {
println(it + " World")
it + " World"
}
println(result) //Hello
}
例举完 Kotlin 标准库常用的几个扩展函数之后,我们会发现它们都是高阶函数,而且还都使用了inline。
inline
Kotlin 的内联函数是使用inline修饰的函数,从编译器角度将函数的函数体复制到调用处实现内联。
本质上,内联函数的使用是空间换取时间的过程。
示例1
在 main 函数中,分别使用内联函数和非内联函数打印一段文字。
fun nonInlined(block: () -> Unit) { // 不用内联的函数
block()
}
inline fun inlined(block: () -> Unit) { // 使用内联的函数
block()
}
fun main(args: Array<String>) {
nonInlined {
println("do something with nonInlined")
}
inlined {
println("do something with inlined")
}
}
其中 nonInlined 需要创建 Function0 对象。而使用了内联的 inlined 函数,它不用再创建 Function0 对象,直接被复制到被调用处。
示例2
对 Closeable 类进行扩展,让它支持 Java 的try-with-resources特性。其实,在 Kotlin 1.2 后已经在 Closeable.kt 中增加了扩展函数 use(),跟下面的代码类似:
inline fun <T : Closeable?, R> T.use(block: (T) -> R): R {
var closed = false
try {
return block(this)
} catch (e: Exception) {
closed = true
try {
this?.close()
} catch (closeException: Exception) {
}
throw e
} finally {
if (!closed) {
this?.close()
}
}
}
使用这个 use() 方法:
val sourceString = "write something to test.txt"
val sourceByte = sourceString.toByteArray()
val file = File("test.txt")
if (!file.exists()) {
file.createNewFile()
}
FileOutputStream(file).use { // 使用了扩展函数 use 之后,就无需再主动关闭FileOutputStream
it.write(sourceByte)
}
Kotlin 的代码节省了try…catch…finally语句,并自动关闭了文件输出流。
小结一下内联函数的特性:
- 内联函数中有函数类型的参数,那么该函数类型的参数默认也是内联的。除非,显示使用noinline进行修饰,那样该函数类型就不再是内联的。
- 内联函数的优点是效率高、运行速度快。
- 内联函数的缺点是编译器会生成比较多的代码,所以内联函数不要乱用。