Kotlin基础知识_05-Kotlin标准函数_静态方法
Kotlin基础知识_05-Kotlin标准库函数&静态方法
1. 标准库函数 let(), with(), run(), apply(), repeat()
Kotlin的标准库函数类似于C语言的标准库函数,在任意的位置均能调用。
1.1 let()
以调用的对象本身作为block函数块的参数,并且返回block函数块的结果,这个block函数块可以是一个lambda表达式,它的最后一行代码将作为返回结果:
ex:
data class Car(var color: String = "红色", var weight: Int = 20) {
fun run() = println("This car is running")
fun ring() = println("This car is -ringing-.")
}
fun main() {
val car = Car()
println("car info(before call let): $car")
val result = car.let {
it.color = "绿色"
it.weight = 300
it.run()
it.ring()
123
}
println("car info(after call let): $result")
}
输出:
car info(before call let): Car(color=红色, weight=20)
This car is running
This car is -ringing-.
car info(after call let): 123
可以看到 Lambda 表达式中的code 均得到了执行,并且返回了lambda表达式的结果:123
.
1.2 with()
在传入的对象上调用指定的block函数块,并且返回block函数块的最后一行代码。
例如,输入log时经常会用到字符串拼接:
public class Test {
public static void main(String[] args) {
StringBuilder builder = new StringBuilder("------------ Person Info -------------");
builder.append("\n");
builder.append("Name: zhangSan\n");
builder.append("Age: 16\n");
builder.append("Address: Beijing\n");
System.out.println(builder);
}
}
利用with()
函数则可以简化上述code:
fun main() {
val result = with(StringBuilder("------------ Person Info -------------")) {
append("\n")
append("Name: zhangSan\n")
append("Age: 16\n")
append("Address: Beijing\n")
toString()
}
println(result)
}
输出:
------------ Person Info -------------
Name: zhangSan
Age: 16
Address: Beijing
1.3 run()
该函数有两种实现:
一种是直接调用run()函数,传入一个函数块,然后返回该函数块的最后一行代码;
另一种是在指定的对象上调用,将该对象作为函数块的上下文,然后返回函数块的最后一行代码;
直接调用run()函数
fun main() {
val result = run {
println("abc")
println("efg")
123
}
println(result)
}
输出:
abc
efg
123
在对象上调用run()函数
fun main() {
val result = StringBuilder("------------ Person Info -------------").run {
append("\n")
append("Name: zhangSan\n")
append("Age: 16\n")
append("Address: Beijing\n")
toString()
}
println(result)
}
输出:
------------ Person Info -------------
Name: zhangSan
Age: 16
Address: Beijing
这里新建了一个匿名对象 StringBuilder("------------ Person Info -------------")
, 然后在它身上调用 run()
函数。
1.4 apply()
在当前对象上调用指定的函数块,并且返回这个被调用的对象本身。
ex:
val result = StringBuilder("------------ Person Info -------------").apply {
append("\n")
append("Name: zhangSan\n")
append("Age: 16\n")
append("Address: Beijing\n")
123
}
println(result)
输出:
------------ Person Info -------------
Name: zhangSan
Age: 16
Address: Beijing
Note:
它和
let()
,with()
,run()
函数的最大区别在于,前面三个函数返回的均是传入的函数块的结果,即Lambda表达式的最后一行code,apply()
函数返回的则是调用的对象本身,比如我在上述Lambda表达式的最后一行写的是123,但是实际上打印出的result的结果是仍然是StringBuilder()
对象。
1.5 repeat()
让指定的函数块执行N次:
ex: 在原有字符串的基础上重复添加N个相同的字符串:
fun String.repeatTimes(num: Int): String {
val builder = StringBuilder(this)
repeat(num) {
builder.append(this)
}
return builder.toString()
}
fun main() {
val str = "Abcd"
val newStr = str.repeatTimes(4)
println("newStr: $newStr")
}
输出:
newStr: AbcdAbcdAbcdAbcdAbcd
2. 静态方法
静态方法在某些编程语言里面又叫作类方法,指的就是那种不需要创建实例就能调用的方法,所有主流的编程语言都会支持静态方法这个特性。java中定义静态方法很简单,给方法加上static
关键字就行了:
public class Util {
public static void doAction() {
System.out.println("do action");
}
}
调用时直接写成 Util.doAction()
就能调用。
kotlin中的静态方法和java的稍有区别,分为伪静态方法和真实的静态方法两种。
2.1 伪静态方法
所谓伪静态方法,就是说它从语法结构上看起来像是一个静态方法,但实际上它不是一个静态方法,这样的定义主要会出现在以下两种语法结构中:
2.1.1 单例类
object Utils {
fun formatString() = println("format a string")
}
fun main() {
Utils.formatString()
}
输出:
format a string
Utils.formatString()
这种看起来跟java中的静态方法很像,都是以类.方法名
的形式去调用,但实际上这个 formatString()
不是静态方法。当然kotlin也推荐我们以这种单例类的方式去实现工具类,毕竟看起来像。
2.1.2 companion object
class Utils {
fun splitString() = println("split a string")
companion object {
fun formatString() = println("format a string")
}
}
fun main() {
Utils().splitString()
// 伴生类中的方法也可以写成类似于静态方法这种调用形式
Utils.formatString()
}
输出:
split a string
format a string
Kotlin 规定,所有定义在companion object
中的方法都可以使用类似于Java静态方法的形式调用,companion object
这个关键字实际上会在Utils类的内部创建一个伴生类,而formatString()
方法就是定义在这个伴生类里面的实例方法。只是Kotlin会保证Util类始终只会存在一个伴生类对象,因此调用Utils.formatString()
方法实际上就是调用了Utils
类中伴生对象的formatString()
方法。
不过这个也不是真正的静态方法。
2.2 真实的静态方法
上面两种语法结构定义的方法其实都不是真实的静态方法,在java代码中是没有办法以类.方法名
的形式去直接调用的,
比如我在kotlin文件中定义了以下两个kotlin类:
TestKotlin.kt
object ByteUtils {
fun bytesToHexString() = println(">>>>>>>>>>>>> bytesToHexString <<<<<<<<<<<<<")
}
class StringUtils {
fun splitString() = println("split a string")
companion object {
fun formatString() = println("---------------- format a string ------------")
}
}
在java类中调用kotlin单例类的方法
编译器报错:
直接提示 bytesToHexString()
是一个非静态方法。
在java类中调用kotlin companion object 中的方法
编译器报错:
提示在StringUtils
类中根本找不到 formatString() 方法。
除非写成下面的形式, 才允许正常调用:
public class Test {
public static void main(String[] args) {
ByteUtils.INSTANCE.bytesToHexString();
StringUtils.Companion.formatString();
}
}
输出;
>>>>>>>>>>>>> bytesToHexString <<<<<<<<<<<<<
---------------- format a string ------------
如果一定要在 kotlin中定义真实的静态方法,可通过下面两种方式:
2.2.1 使用 @JvmStatic 注解
分别给上述单例类和 companion object
中定义的实例方法加上 @JvmStatic
注解:
object ByteUtils {
@JvmStatic
fun bytesToHexString() = println(">>>>>>>>>>>>> bytesToHexString <<<<<<<<<<<<<")
}
class StringUtils {
fun splitString() = println("split a string")
companion object {
@JvmStatic
fun formatString() = println("---------------- format a string ------------")
}
}
然后在java代码中就可以以类名.方法名
的形式去调用了:
public class Test {
public static void main(String[] args) {
ByteUtils.bytesToHexString();
StringUtils.formatString();
}
}
输出:
>>>>>>>>>>>>> bytesToHexString <<<<<<<<<<<<<
---------------- format a string ------------
给单例类或companion object中的方法加上@JvmStatic
注解,那么Kotlin编译器就会将这些方法编译成真正的静态方法。
注意:
Kotlin 规定:
@JvmStatic
注解只能加在单例类或companion object中的方法上,如果你尝试加在一个普通方法上,会直接提示语法错误。
2.2.2 使用顶层方法
顶层方法(Top Level Method), 即没有定义在任何类中的方法,比如经常使用的main
方法。Kotlin编译器会将所有的顶层方法全部编译成静态方法,因此只要你定义了一个顶层方法,那么它就一定是静态方法。想要定义一个顶层方法,首先需要创建一个Kotlin文件。对着任意包名右击 → New → Kotlin File/Class,在弹出的对话框中输入文件名即可。注意创建类型要选择File,如图所示:
BitmapUtil
fun decodeBitmap() = println("******************* decode bitmap *****************")
decodeBitmap()
将会自动成为顶层方法,在java代码中可以这样调用:
public class Test {
public static void main(String[] args) {
BitmapUtilKt.decodeBitmap();
}
}
输出:
******************* decode bitmap *****************
注意:
在java里调用时仍然要以
类.方法名
的形式去调用,只不过这里的类名就是新建的Kotlin 文件名罢了,在kotlin里面调用则无此限制,直接写方法名即可:object ByteUtils { @JvmStatic fun bytesToHexString() = println(">>>>>>>>>>>>> bytesToHexString <<<<<<<<<<<<<") } class StringUtils { fun splitString() = println("split a string") companion object { @JvmStatic fun formatString() = println("---------------- format a string ------------") } } fun main() { StringUtils().splitString() // 伴生类中的方法也可以写成类似于静态方法这种调用形式 StringUtils.formatString() decodeBitmap() }
输出:
split a string ---------------- format a string ------------ ******************* decode bitmap *****************
可以看到,直接写
decodeBitmap()
就行。
<完>