1、对象声明
2、伴生对象
3、@JvmField 和 @JvmStatic 的使用
4、const 关键字
5、object,companion和const区别
6、伴生对象的扩展函数和扩展属性
一、对象声明
Kotlin 使用 object 关键字来声明一个静态对象。
在kotlin中,类是没有显式的static方法和static成员变量的,都是通过伴生对象的形式间接提供的。
fun main() {
Student.eat()
}
object Student {
fun eat() {
print("吃吃吃")
}
}
Student 相当于java的
public final class Student2 {
public static void say() {
System.out.println("Hello");
}
}
二、伴生对象
Kotlin 中,在类中定义的对象(object)声明,可使用 companion 修饰,这样此对象(object)就是伴生对象了
class Teacher {
companion object test {
var name: String = "A老师"
fun say() {
print("好好学习")
}
}
}
在上面的 Teacher 类中, test 是一个伴生对象,其中有一个 name 属性 和 say 方法.
在kotlin中调用:
fun main() {
Teacher.say()
print(Teacher.name)
}
通过上面的 Teacher.say() 和 Teacher.name 代码不难看出来,类似于 Java 中使用类访问静态成员的语法。因为 Kotlin 取消了 static 关键字,所以 Kotlin 引入伴生对象来弥补没有静态成员的不足。可见,伴生对象的主要作用就是为其所在的外部类模拟静态成员。其中可以省略test对象名称,实际上是在这个类内部创建了一个名为 Companion 的静态单例内部类,伴生对象中定义的属性会直接编译为外部类的静态字段,而函数会被编译为伴生对象的方法。
注意:1、一个类里面只能声明一个内部关联对象,即关键字 companion 只能使用一次。
在 java 中调用:
public static void main(String[] args) {
Teacher.Companion.say();
System.out.println( Teacher.Companion.getName());
}
如果伴生对象有名称:
类名.伴生对象名.方法名()
类名.半生对象名.属性的setter,getter方法
Teacher.test.say();
System.out.println( Teacher.test.getName());
如果伴生对象没有名称,则使用 Companion 关键字:
类名.Companion.方法名()
类名.Companion.属性的setter,getter方法
Teacher.Companion.say();
System.out.println( Teacher.Companion.getName());
三、 @JvmField 和 @JvmStatic 的使用
我们知道了可以在 Java 代码中调用 Kotlin 中伴生对象的成员,类似于 Java 类中的静态成员。但是看上去和 Java 中的还是略有区别,因为类名和方法名/属性setter,getter方法名之间多了个伴生对象的名称或者 Companion 关键字。为了和 Java 中的调用看上去一样,Kotlin 为我们提供了 @JvmField 和 @JvmStatic 两个注解。
@JvmField 使用在属性上,@JvmStatic 使用在方法上。
class Teacher {
companion object test {
@JvmField
var name: String = "A老师"
@JvmStatic
fun say() {
print("好好学习")
}
}
}
java调用
public static void main(String[] args) {
Teacher.say();
System.out.println( Teacher.name);
}
这个注解,只对java的调用方式有影响,对kotlin的调用方法,没影响.
四、const 关键字
在伴生对象中,我们可能需要声明一个常量,目的是等同于 Java 中的静态常量。有两种方式,一种是上面所提到的使用 @JvmField 注解,另一种则是使用 const 关键字修饰。这两种声明方式都等同于 Java 中 static final 所修饰的变量。
class Teacher {
companion object test {
const val age: Int = 20
@JvmField
var name: String = "A老师"
@JvmStatic
fun say() {
print("好好学习")
}
}
}
kotlin 调用:
Teacher.say()
print(Teacher.name)
print(Teacher.age)
java调用:
public static void main(String[] args) {
Teacher.say();
System.out.println(Teacher.name);
System.out.println(Teacher.age);
//如果不写 Teacher 类的 伴生对象 test 中的 const 关键字
System.out.println(Teacher.test.getAge());
}
const 关键字使用的影响只是在 Java 中调用方式不同,在 Kotlin 中并无影响。
五、object,companion和const区别
object:用对象表达式和对象声明实现Java匿名内部类这种情况,即匿名类的实现对象为object。
companion object{} :伴生对象,虽然调用的时候类似static,但它依然是对象的实例成员,并且可以实现接口
const :编译时常量。1.String或基本类型进行初始化;2.没有自定义getter;3对象成员或顶级(Top-level)。从实际上看,它更符合static final的常量
六、伴生对象的扩展函数和扩展属性
fun Teacher.test.sleep() {
print("我说扩展方法")
}
var Teacher.test.sex
get() = 3
set(value) {
}
val Teacher.test.height
get() = 180
class Teacher {
companion object test {
val age: Int = 20
@JvmField
var name: String = "A老师"
@JvmStatic
fun say() {
print("好好学习")
}
}
}
1、如果伴生对象有名称的话,使用类名.伴生对象名.方法名()
来扩展,否则使用 类名.Companion.方法名()
来扩展
2、扩展属性不能有初始值,没有 field 来存储属性值;
3、扩展属性因为没字段来存储值,所以为计算属性;
4、扩展 var 属性必须提供 setter 和 getter 方法,扩展 val 属性必须提供 getter 属性。
调用:
fun main() {
print(Teacher.sleep())
print(Teacher.sex)
print(Teacher.height)
}
小结:
1、每个类可以最多有一个用companion object 修饰的伴生对象;
2、伴生对象的成员类似于 Java 的静态成员;
3、使用 const 关键字修饰常量,类似于 Java 中的 static final修饰。
4、可以使用 @JvmField 和 @JvmStatic 类似于 Java 中调用静态属性和静态方法.