Kotlin 实现静态的几种方式详解

一、将 kotlin 编译成 java

先来个题外话,我们如何看 kotlin 对应的 java 代码,kotlin 最终还是要编译成 java class 在 JVM 上运行的,有时我们的确是想看看用 kotlin 写完的代码编译完了是什么样子,这样有助于我们理解 kotlin 语法

其实很简单,AS tools 工具里面有提供

  1. tools -> Show kotlin Bytecode

  2. 点击 Decompile

  3. ok ,这样就行了


二、kotlin 实现静态的方式

在 kotin 语言中其实没有 java static 的这个概念,基本都是用一个静态对象来模拟 class 的静态属性和方法,目前有4种实现方式:

  • companion object - 伴随对象,声明单例的方式
  • @JvmField + @JvmStatic 注解 - 使用注解标签声明 static 的部分
  • object 单例 - 静态单例其实和 companion object 类似
  • const - 包内唯一性,脱离类的束缚,kotlin 的特性,在 java 中会编译生成一个 kotlin.kt 的文件专门对齐提供支持

1、companion object

companion object 伴随对象这是我们在 kotlin 中最常用的方式了吧,在 companion object 里面我们即可以声明属性,也可以声明方法,kotlin 中的调用方式感觉和 java 的 static 一样,举个例子看下面:

class BookKotlin {

    var name: String = "AA"

    fun speak() {}

    companion object instance {

        var nameStatic: String = "BB"

        fun speakStatic() {}

    }
}

kotlin 中使用如下:

kotlin 中调用静态方法和属性

kotlin 中调用成员方法和属性

看上面图,我们在 kotlin 中使用时感觉的确是和 java 中的 static 一样,静态参数方法和成员参数方法能有效区别开来,下面我们来看看 java 中使用

java 中使用如下:

类名. 没有静态属性和方法,只有一个静态对象

这个静态对象下我们可以找到我们声明的静态属性和方法

new 一个对象我们可以使用成员变量和方法

kotlin 的使用 ok ,但是一到 java 上就全变了,为啥,因为 kotlin 最终也是会编译成 java 文件去 JVM 运行的,kotlin 并没有提供自己特有的 VM ,所以kotlin 代码还是要转换成 java 代码的,要不 kotlin 怎么宣传 kotlin 和 java 可以实现无缝调用

kotlin 中所有的成员变量,不管是不是 static 的都有 get/set 方法,另外 kotlin 并没有把我们声明的静态参数和方法声明成 static 的,而是通过 instance 这个静态对象中转使用的,这就让我们迷惑了,kotlin 变成成 java 之后到底上啥样的,会不会和我们的初衷不同,影响我们使用

instance 这个静态对象的名字是采用 companion object 后面跟的名字,可以不写,不写的话默认就是 INSTANCE(版本不同会有变化)

下面我们把 kotlin 转换成 java 代码来一探究竟

把 kotlin 代码转成 java:

public final class BookKotlin {

   private static String nameStatic = "BB";

   public static final BookKotlin.instance instance = new BookKotlin.instance((DefaultConstructorMarker)null);

   private String name = "AA";

   public final String getName() {
      return this.name;
   }

   public final void setName(@NotNull String var1) {
      Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
      this.name = var1;
   }

   public final void speak() {
   }

   public static final class instance {
      @NotNull
      public final String getNameStatic() {
         return BookKotlin.nameStatic;
      }

      public final void setNameStatic(@NotNull String var1) {
         Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
         BookKotlin.nameStatic = var1;
      }

      public final void speakStatic() {
      }

      private instance() {
      }

      // $FF: synthetic method
      public instance(DefaultConstructorMarker $constructor_marker) {
         this();
      }
   }
}

看到 java 代码后,大家都彻底清楚了吧, companion object 伴随对象真不是白叫的,真的是个对象,在 class 内部添加一个 static final class 的静态内部类实现对象来模拟 static 特性


2、@JvmField + @JvmStatic 注解

上面我们见识了 companion object 伴随对象,那么 kotlin 是不是真的无法实现 static 了,也不是,kotlin 还是提供了相关办法,这就是 @JvmField + @JvmStatic 注解,其意思是声明成员和方法使用 JVM 提供的特性

  • @JvmField - 修饰静态变量
  • @JvmStatic - 修饰静态方法
  • @JvmField@JvmStatic 只能写在 object 修饰的类或者 companion object 里,写法虽然有些别扭,但是效果是真的是按 static 来实现的

我们把上面的代码修改下:

class BookKotlin {

    companion object {

        @JvmField
        var nameStatic: String = "BB"

        @JvmStatic
        fun speakStatic() {
        }
    }

    var name: String = "AA"

    fun speak() {}
}

kotlin 中使用如下:

java 中使用如下:

把 kotlin 代码转成 java:

public final class BookKotlin {

   @JvmField
   public static String nameStatic = "BB";

   @JvmStatic
   public static final void speakStatic() {
      Companion.speakStatic();
   }

   public static final BookKotlin.Companion Companion = new BookKotlin.Companion((DefaultConstructorMarker)null);

   private String name = "AA";

   @NotNull
   public final String getName() {
      return this.name;
   }

   public final void setName(@NotNull String var1) {
      Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
      this.name = var1;
   }

   public final void speak() {
   }


   public static final class Companion {
      @JvmStatic
      public final void speakStatic() {
      }

      private Companion() {
      }

      // $FF: synthetic method
      public Companion(DefaultConstructorMarker $constructor_marker) {
         this();
      }
   }
}


3、object 单例

kotlin 自身提供了一种单例实现方式:object ,直接用来修饰 class ,用 object 修饰的类不能 new 对象,只能使用 object 提供的单例

object BookKotlin {

    var name: String = "AA"

    fun speak() {}
}

kotlin 中使用如下:

object 修饰的类不能创建对象了

java 中使用如下:

把 kotlin 代码转成 java:

public final class BookKotlin {

   private static String name;
   public static final BookKotlin INSTANCE;

   public final String getName() {
      return name;
   }

   public final void setName(@NotNull String var1) {
      Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
      name = var1;
   }

   public final void speak() {
   }

   static {
      BookKotlin var0 = new BookKotlin();
      INSTANCE = var0;
      name = "AA";
   }
}

虽然 name 是 static 的了,但还是 private 私有的,还是得通过静态单例来中转调用,真的是单例


4、const

const 写在 class 外面,效果 = @JvmField,但是不能修饰方法,也不能和 @JvmField 混用,一般就是用来声明常用值的,用处不多,而且只能用 val ,var 不行,想要修饰方法的话,不写 const 就行

const val name: String = "AA"
fun adk(){}
class BookKotlin {

    fun speak() {}
}

kotlin 中使用如下:
kotlin 没有包的概念,所以直接用,注意这么写其实已经相当于脱离了类的范围,一个包的范围内不能重名的

java 中使用如下:


这个 BookKotlinKt 文件就是为了专门支持这个 kotlin 特性而生成的辅助类,java 中我们是通过这个类来调用 const 声明的内容的,为啥要有这个类呢,因为 java 是有包这个概念的,所有的文件必须要有统一的地址规范,所以 kotlin 层面只能是提供 XXXKt 文件来单独支持了,其实这已经脱离了 java 范围

把 kotlin 代码转成 java:

public final class BookKotlin {
   public final void speak() {
   }
}

public final class BookKotlinKt {
   @NotNull
   public static final String name = "AA";

   public static final void adk() {
   }
}

在 java 代码中是以 kotlin 辅助类存在的,这样用的人真的是非常少,限制太大

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值