Kotlin的标准函数指的是Standard.kt文件中定义的函数,任何Kotlin代码都可以调用所有的标准函数。
该函数提供了函数式API的编程接口,并将原始调用对象作为参数传递到Lambda表达式中。
/**
* Calls the specified function [block] with `this` value as its argument and returns its result.
*
* For detailed usage information see the documentation for [scope functions](https://kotlinlang.org/docs/reference/scope-functions.html#let).
*/
@kotlin.internal.InlineOnly
public inline fun <T, R> T.let(block: (T) -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block(this)
}
let函数主要配合?.进行使用,可以在外部判断后,如果对象不为空,则将其传入let的lambda表达式之中,处理该对象的多条调用。
fun doStudy() {
study?.let {
it.readBooks()
it.doHomework()
}
}
同时,let函数还可以处理全局变量的判空问题。如果使用if语句则仍然会提示错误,这是因为全局变量随时有可能被其他线程修改,即使做了判空处理,也会有空指针的风险。
with函数接收两个参数:第一个参数可以是一个任意类型的对象,第二个参数是一个Lambda表达式。with函数会在Lambda表达式中提供第一个参数对象的上下文,并使用Lambda表达式中的最后一行代码作为返回值返回。
val result = with(obj) {
//这里是obj的上下文
"value"//with函数的返回值
}
with函数的左右是可以在连续调用同一个对象的多个方法时让代码变得更加精简,如下所示:
val list = listOf<String>("Apple", "Banana", "Orange", "Pear", "Grape")
val builder = StringBuilder()
builder.append("Start eating fruits.\n")
for (fruit in list) {
builder.append(fruit).append("\n")
}
builder.append("Ate all fruits")
val result = builder.toString()
println(result)
使用with函数精简之后
val list = listOf<String>("Apple", "Banana", "Orange", "Pear", "Grape")
val result = with(StringBuilder()) {
append("Start eating fruits.\n")
for (fruit in list) {
append(fruit).append("\n")
}
append("Ate all fruits")
toString()
}
println(result)
run和with非常类似,润函数通常不会直接调用,而是要在某个对象的基础上调用。run只接收一个Lambda参数,并且会在Lambda表达式中提供调用对象的上下文。
val result = obj.run {
//这里是obj的上下文
"value" //run函数的返回值
}
对于with函数前面的可以这样修改成run函数版本
val list = listOf<String>("Apple", "Banana", "Orange", "Pear", "Grape")
val result = StringBuilder().run {
append("Start eating fruits.\n")
for (fruit in list) {
append(fruit).append("\n")
}
append("Ate all fruits")
toString()
}
println(result)
apply函数也是在某个对象上调用的,并且只接收一个Lambda参数,也会在Lambda表达式中提供调用对象的上下文,但是apply函数无法指定返回值,而是会自动返回调用对象本身。
apply的版本为
val list = listOf<String>("Apple", "Banana", "Orange", "Pear", "Grape")
val result = StringBuilder().apply {
append("Start eating fruits.\n")
for (fruit in list) {
append(fruit).append("\n")
}
append("Ate all fruits")
}
println(result.toString())
返回的是对象本身,调用toString方法转成String。
Java中静态方法可以用类名调用,而在Kotlin中没有静态方法的概念。
对于Java中工具类的这种功能,Kotlin中推荐使用单例类的方式实现。
public class Util {
public static void doAction() {
System.out.println("do action");
}
}
1、使用单例类
object Util {
fun doAction() {
println("do action"}
}
}
单例类就可以像Java中的静态方法一样使用Util.doAction()进行调用。使用object关键字后,Kotlin会自动帮我们创建一个类,并保证这个类全局只有一个。
但是使用单例类的方式会使得单例类中的所有方法都变成了类似静态调用的方式。如果希望将其中的一个方法变成静态方法的调用方式,可以使用companion object。
2、使用companion object
class Util {
fun doAction1() {
println("do action1"}
}
companion object {
fun doAction2() {
println("do action2"}
}
}
}
companion object这个关键字实际上会在Util类的内部创建一个伴生类,而doAction2方法就是定义在这个伴生类里面的实例方法。只是Kotlin会保证Util类中只会存在一个伴生类对象,所以可以像静态方法式的调用。
上述两种方式都不是真正的静态方法,而是提供一些语法特性来支持静态方法调用的方式,Kotlin也提供了两种真正实现静态方法。
3、使用注解
如果给单例类和companion object中的方法加上@JvmStatic注解,那么Kotlin编译器就会将这些方法编译成真正的静态方法。
class Util {
fun doAction1() {
println("do action1"}
}
companion object {
@JvmStatic
fun doAction2() {
println("do action2"}
}
}
}
需要注意的是,这个注解只能加在单例类和companion object中的方法上。这样这些方法就是真正的静态方法了,不管是在Kotlin还是在Java中都可以静态调用。
4、使用顶层方法
顶层方法指的是那些没有定义在任何类中的方法,Kotlin编译器会将这些方法全部编译成静态方法。
fun doSomething() {
println("do something")
}
在Kotlin中可以直接使用函数名进行调用,但是在Java中怎么调用呢。Java中所有的方法都必须定义在类中,所以Kotlin编译器会将顶层函数所在的文件名编译成一个类,doSomething就是以静态方法的形式定义在该类中的,所以Java中可以通过Kotlin文件名和方法名调用。