静态方法在某些编程语言里面又叫作类方法,指的就是那种不需要创建实例就能调用的方法,所有主流的编程语言都会支持静态方法这个特性。
在Java中定义一个静态方法非常简单,只需要在方法上声明一个static
关键字就可以了,如下所示:
java
public class Util {
public static void xxxx() {
System.out.println("xxxx");
}
}
这是一个非常简单的工具类,上述代码中的xxxx
方法就是一个静态方法。调用静态方法并不需要创建类的实例,而是可以直接以Util.xxxx()
这种写法来调用。因而静态方法非常适合用于编写一些工具类的功能,因为工具类通常没有创建实例的必要,基本是全局通用的。
但是和绝大多数主流编程语言不同的是,Kotlin却极度弱化了静态方法这个概念,想要在Kotlin中定义一个静态方法反倒不是一件容易的事。
那么Kotlin为什么要这样设计呢?因为Kotlin提供了比静态方法更好用的语法特性,并且我们在上一节中已经学习过了,那就是单例类。
像工具类这种功能,在Kotlin中就非常推荐使用单例类的方式来实现,比如上述的Util
工具类,如果使用Kotlin来实现的话就可以这样写:
Kotlin
object Util {
fun xxxx() {
println("xxxx")
}
}
虽然这里的xxxx()
方法并不是静态方法,但是我们仍然可以使用Util.xxxx()
的方式来调用,这就是单例类所带来的便利性。
不过,使用单例类的写法会将整个类中的所有方法全部变成类似于静态方法的调用方式,而如果我们只是希望让类中的某一个方法变成静态方法的调用方式该怎么办呢?这个时候就可以使用刚刚在最佳实践环节用到的companion object
了,示例如下:
Kotlin
class Util {
fun xxxx1() {
println("xxxx1")
}
companion object {
fun xxxx2() {
println("xxxx2")
}
}
}
这里首先我们将Util
从单例类改成了一个普通类,然后在类中直接定义了一个xxxx()
方法,又在companion object
中定义了一个xxxx2()
方法。现在这两个方法就有了本质的区别,因为xxxx()
方法是一定要先创建Util
类的实例才能调用的,而xxxx2()
方法可以直接使用Util.xxxx2()
的方式调用。
不过,xxxx2()
方法其实也并不是静态方法,companion object
这个关键字实际上会在Util
类的内部创建一个伴生类,而xxxx2()
方法就是定义在这个伴生类里面的实例方法。只是Kotlin会保证Util
类始终只会存在一个伴生类对象,因此调用Util.xxxx2()
方法实际上就是调用了Util
类中伴生对象的xxxx2()
方法。
由此可以看出,Kotlin确实没有直接定义静态方法的关键字,但是提供了一些语法特性来支持类似于静态方法调用的写法,这些语法特性基本可以满足我们平时的开发需求了。
然而如果你确确实实需要定义真正的静态方法, Kotlin仍然提供了两种实现方式:注解和顶层方法。下面我们来逐个学习一下。
先来看注解,前面使用的单例类和companion object
都只是在语法的形式上模仿了静态方法的调用方式,实际上它们都不是真正的静态方法。因此如果你在Java代码中以静态方法的形式去调用的话,你会发现这些方法并不存在。而如果我们给单例类或companion object
中的方法加上@JvmStatic
注解,那么Kotlin编译器就会将这些方法编译成真正的静态方法,如下所示:
Kotlin
class Util {
fun xxxx1() {
println("xxxx1")
}
companion object {
@JvmStatic
fun xxxx2() {
println("xxxx2")
}
}
}
注意,@JvmStatic
注解只能加在单例类或companion object
中的方法上,如果你尝试加在一个普通方法上,会直接提示语法错误。
由于xxxx2()
方法已经成为了真正的静态方法,那么现在不管是在Kotlin中还是在Java中,都可以使用Util.xxxx2()
的写法来调用了。
再来看顶层方法,顶层方法指的是那些没有定义在任何类中的方法,比如我们在上一节中编写的main()
方法。Kotlin编译器会将所有的顶层方法全部编译成静态方法,因此只要你定义了一个顶层方法,那么它就一定是静态方法。
想要定义一个顶层方法,首先需要创建一个Kotlin文件。对着任意包名右击 → New → Kotlin File/Class,在弹出的对话框中输入文件名即可。注意创建类型要选择File。
点击"OK"完成创建,这样刚刚的包名路径下就会出现一个Helper.kt文件。现在我们在这个文件中定义的任何方法都会是顶层方法,比如这里我就定义一个doSomething()
方法吧,如下所示:
Kotlin
fun doSomething() {
println("do something")
}
刚才已经讲过了,Kotlin编译器会将所有的顶层方法全部编译成静态方法,那么我们要怎么调用这个doSomething()
方法呢?
如果是在Kotlin代码中调用的话,那就很简单了,所有的顶层方法都可以在任何位置被直接调用,不用管包名路径,也不用创建实例,直接键入doSomething()
即可,如下所示:
Kotlin
fun main(){
doSomething()
}