Jiacheng

aha

野比大雄

Kotlin 中如何定义常量

Jiacheng / 2017-04-11


在 Java 中,一般都是使用如下的方式定义一个常量:

public static final double PI = 3.14159265358979323846;

但是在 Kotlin 中没有 static 这个关键字,只有两个声明变量的关键字,分别是 varval

对于如下的这种声明:

var a = 10
val b = 11

其对应的 Java 代码为:

private int a = 10;
private final int b = 11;

public final int getA() {
    return this.a;
}

public final void setA(int var1) {
    this.a = var1;
}

public final int getB() {
    return this.b;
}

即使用 var 声明的变量跟普通的 Java 变量一样,有对应的 get 与 set 方法,而 val 声明的变量对应于 Java 中使用了 final 关键字的变量,只有 get 方法,也就是说不能改变其值,只能读取。

但是,如果把变量 b 的 get 重写为改为这种:

val b = 11
     get() {return field +1}

则对应的 Java 代码则变为:

public final int getB() {
    return this.b + 1;
}

即读取的值是声明的值加1,如果把 b 的 get 方法重写为return System.currentTimeMillis(),则每次得到的 b 的值都不相同。

由此来看,val 声明的变量并不能称为常量,从对应的 Java 代码也能看出,val 声明的变量是在runtime的时候赋值的。而 Java 中的 static 则是在 CompileTime 就已经完成内存分配与赋值。

那么 Kotlin 中声明一个常量需要用到另外一个关键字 constconst 是用来声明 CompileTime 常量的。

如果在一个普通类里面直接进行如下声明:

const val c = 20 

则会提示一个错误:const val are only allowed on top level or in objects

kotlin 中 top level 即为包级,in objects 即为在 object 关键字修饰的类中。

于是,Kotlin 中使用 const 定义常量的情况有如下几种:

1. top level(包级属性):

新建一个 Kotlin file ,声明如下:

const val c = 20

使用的时候直接使用变量名可以,比如在包内任何一个地方调用print(c),编译的时候会被编译成静态的变量,对应的Java 代码如下:

public static final int c = 20;

2. 普通类的 companion object

class Test {
   companion object {
       const val c = 20
   }
}

调用的时候直接通过外层类名调用变量名:Test.c 或者 通过对象调用变量名 Test().c

对应的Java代码:

public final class Test {
   public static final int c = 20;
   public static final Test.Companion Companion = 
      new Test.Companion((DefaultConstructorMarker)null);
   }

注意:即使伴生对象的成员看起来像其他语言的静态成员,在运行时他们仍然是真实对象的实例成员。

3. 普通类内部的普通 object 类

class Test {
    object Constant {
        const val d = 20
    }
}

调用的时候通过Test.Constant.d调用,编译后对应的Java代码如下:

public static final class Constant {
    public static final int d = 20;
    public static final Test.Constant INSTANCE;
    static {
        Test.Constant var0 = new Test.Constant();
        INSTANCE = var0;
    }
}

可以看到 Constant 就相当于一个静态内部类,而变量d就是静态类的静态变量。

4. 直接使用 object 修饰的类

object SingletonTest {
    const val c = 20
}

调用的时候直接通过类名调用,如:SingletonTest.c.

object 修饰的类对应的Java代码为:

public final class SingletonTest {
   public static final int c = 20;
   public static final SingletonTest INSTANCE;

   static {
      SingletonTest var0 = new SingletonTest();
      INSTANCE = var0;
   }
}

可以看到这其实是 Kotlin 中单例的一种实现方式,而 c 则为内部静态变量。

以上就是有关 Kotlin 中如何定义常量的总结。