static
修饰符。与Java不同的是在Kotlin的类中不允许你声明静态成员或方法。相反,你必须向类中添加Companion对象来包装这些静态引用: 差异看起来似乎很小,但是它有一些明显的不同。
一:companion伴生对象作用
首先,companion伴生对象是个实际对象的单例实例。你实际上可以在你的类中声明一个单例,并且可以像companion伴生对象那样去使用它。这就意味着在实际开发中,你不仅仅只能使用一个静态对象来管理你所有的静态属性! companion
这个关键字实际上只是一个快捷方式,允许你通过类名访问该对象的内容(如果伴生对象存在一个特定的类中,并且只是用到其中的方法或属性名称,那么伴生对象的类名可以省略不写)。就编译而言,下面的testCompanion()
方法中的三行都是有效的语句。
class TopLevelClass {
companion object {
fun doSomeStuff() {
...
}
}
object FakeCompanion {
fun doOtherStuff() {
...
}
}
}
fun testCompanion() {
TopLevelClass.doSomeStuff()
TopLevelClass.Companion.doSomeStuff()
TopLevelClass.FakeCompanion.doOtherStuff()
}
Kotlin中调用方式可以看出包裹在Companion里的方法直接用
1: 类.方法 : TopLevelClass.doSomeStuff() ,当然也可以使用最原始的
2: 类.Companion.方法 : TopLevelClass.Companion.doSomeStuff(),而此时其实是可以直接省略Companion
3:object声明的静态内部类用 类.内部类.方法 :TopLevelClass.FakeCompanion.doOtherStuff()
二:在java中的调用
上面方法在java中的调用如下
TopLevelClass.Companion.doSomeStuff();
TopLevelClass.FakeCompanion.INSTANCE.doOtherStuff();
和在kotlin的调用中可看出区别
1:Companion包裹的在Kotlin中调用可以选择省略Companion,直接 类.方法,但是在java中就不能省略
2:object声明的静态内部类在java中多了INSTANCE 这个参数
那是不是有其他的方法让Kotlin和java的调用可以一致呢,就涉及到了以下的第三点
三:@JvmStatic注解、@JvmField注解
@JvmField注解:用来修饰静态变量
@JvmStatic注解:用来修饰静态方法
还是用原来的例子,增加变量的注释
class TopLevelClass {
companion object {
@JvmField
val BIG_INTEGER = "BigInteger.ONE"
@JvmStatic
fun doSomeStuff() {
}
}
object FakeCompanion {
@JvmField
val BIG_INTEGER = "BigInteger.ONE"
@JvmStatic
fun doOtherStuff() {
}
}
}
在java中的调用
TopLevelClass.doSomeStuff();
String s = TopLevelClass.BIG_INTEGER;
TopLevelClass.FakeCompanion.doOtherStuff();
String s1 = TopLevelClass.FakeCompanion.BIG_INTEGER;
可以看出和在kotlin的调用是没差别的
四、在companion object中如何调用外部的成员变量
companion object
中调用非静态的成员变量也是调用不到的,将所引用的成员变量也修饰静态的,这样就可以引用到了。