文章主要是针对Kotlin中静态变量的实现方式进行比较以及在java和kotlin编程环境下的差异
对于Kotlin使用方式上一视同仁,对于java就需要额外注意调用方式
一.Kotlin实现静态变量的总览
class Demo3 {
companion object {
//第一种方式
val FIRST_WAY = "first_way"
//第二种方式
const val SECOND_WAY = "second_way"
//第三种方式
@JvmStatic
val THIRD_WAY = "third_way"
//第四种方式
@JvmField
val FOURTH_WAY = "fource_way"
}
}
复制代码
对于Kotlin而言,直接调用
Demo3.XXX_WAY
就可以简单实现静态变量的引用,但是本文从java的角度去分析这四种方式的不同之处,加深对这四种编写方式的理解
二.第一种方式
val FIRST_WAY = "first_way"
反编译下成Java代码看下:
public final class Demo3 {
@NotNull
private static final String FIRST_WAY = "first_way";
@NotNull
public static final Demo3.Companion Companion = new Demo3.Companion((DefaultConstructorMarker)null);
public static final class Companion {
@NotNull
public final String getFIRST_WAY() {
return Demo3.FIRST_WAY;
}
}
}
复制代码
- val修饰的变量本质上在Demo3类中声明了一个私有变量,只不过在伴生类中kotlin生成了一个方法
getFIRST_WAY
- 在java中我们就只能借助于伴生对象类获取到该静态变量:
Demo3.Companion.getFIRST_WAY()
- 在kotlin中就可以简单通过
Demo3.FIRST_WAY
简单调用,反编译这句调用代码:Demo3.Companion.getFIRST_WAY();
- 可以看到和java的调用方式一样,只不过kotlin帮助我们做了封装,隐藏了部分细节,实现更加简单的调用
三.第二种方式
const val SECOND_WAY = "second_way"
反编译成java代码:
public final class Demo3 {
@NotNull
public static final String SECOND_WAY = "second_way";
@NotNull
public static final Demo3.Companion Companion = new Demo3.Companion((DefaultConstructorMarker)null);
public static final class Companion {
}
}
复制代码
- 通过这种方式声明的静态变量是定义在Demo3类中公有的属性,和java中定义的公有的静态变量一模一样,获取方式与Companion伴生对象无关,所以java中调用该变量的方式和kotlin的调用方式一模一样
- 使用const val需要注意这种方式有两个限制:
- 赋值的value必须是常量
- 属性的类型必须是String和基本包装类型,比如Int、Long、Float等
四.第三种方式
@JvmStatic val THIRD_WAY = "third_way"
反编译下:
public final class Demo3 {
@NotNull
private static final String THIRD_WAY = "third_way";
@NotNull
public static final Demo3.Companion Companion = new Demo3.Companion((DefaultConstructorMarker)null);
@NotNull
public static final String getTHIRD_WAY() {
Demo3.Companion var10000 = Companion;
return THIRD_WAY;
}
public static final class Companion {
@NotNull
public final String getTHIRD_WAY() {
return Demo3.THIRD_WAY;
}
}
}
复制代码
- 可以看到其实这种方式就是在第一种方式的基础上,在Demo3类中增加了获取该静态变量的静态公有方法,所以在java中比第一种方式多提供了一种调用方式:
Demo3.Companion.getFIRST_WAY()
(第一种方式)Demo3.getFIRST_WAY()
(增加的)
- 总体而言不推荐这种方式来声明一个静态变量
五.第四种方式
@JvmField val FOURTH_WAY = "fource_way"
@JvmField注解可以简单理解为保留变量声明时指定的访问修饰符:
- kotlin中普通的val和var修饰的属性会被默认设置为private类型,并自动帮助我们生成对应属性的set或者get访问方法,我们指定属性的访问修饰符时其实指定的是其生成的set或者get方法的访问修饰符,而不是变量的访问修饰符,变量最终还是private
- 当给这些属性加上@JvmField注解时,那么当我们指定属性访问的属性修饰符类型的是什么最终就是什么
反编译下代码:
public final class Demo3 {
@JvmField
@NotNull
public static final String FOURTH_WAY = "fource_way";
@NotNull
public static final Demo3.Companion Companion = new Demo3.Companion((DefaultConstructorMarker)null);
public static final class Companion {
private Companion() {
}
}
}
复制代码
- 可以从代码中看到,和第二种方式const val的实现方式一模一样,所以调用方式上java和kotlin也是一模一样的
- 和第二种方式最大的区别就是:没有第二种方式的限制—属性类型可以任意且赋值的value也任意,不限于常量
- 获取方式和伴生类对象Companion没有任何关系
- 当const val不满足的话,强烈推荐这种方式
六.总结
- 第一种方式和第三种方式依赖于伴生对象获取静态变量,不是特别推荐
- 第二种方式和第四种方式属于比较推荐的方式,优先使用第二种,当第二种不满足的时候采用第四种
- @JvmStatic比较适合修饰方法,伴生对象和object声明的单例中方法其实都不是静态方法,一般常用的方式就是通过该注解实现真正的静态方法
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END