kotlinで定数を定義する
kotlinで定数を定義する際にはCompanionObjectが使われます。
定数を定義する際にプリミティブ型かStringsであればconst
をつけることができますが、const
がある時とない時の振る舞いの違いを調べてみました。
class Constants {
companion object {
const val NAME = "taku"
}
}
constをつけずに定数を定義した場合
class Constants {
companion object {
val NAME = "taku"
}
}
これをバイトコードで見てみると、
// ================com/hoge/Constants.class =================
// class version 50.0 (50)
// access flags 0x31
public final class com/hoge/Constants {
// access flags 0x1
public <init>()V
L0
LINENUMBER 6 L0
ALOAD 0
INVOKESPECIAL java/lang/Object.<init> ()V
RETURN
L1
LOCALVARIABLE this Lcom/hoge/Constants; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 0x1A
private final static Ljava/lang/String; NAME = "taku"
@Lorg/jetbrains/annotations/NotNull;() // invisible
// access flags 0x8
static <clinit>()V
NEW com/hoge/Constants$Companion
DUP
ACONST_NULL
INVOKESPECIAL com/hoge/Constants$Companion.<init> (Lkotlin/jvm/internal/DefaultConstructorMarker;)V
PUTSTATIC com/hoge/Constants.Companion : Lcom/hoge/Constants$Companion;
L0
LINENUMBER 9 L0
LDC "taku"
PUTSTATIC com/hoge/Constants.NAME : Ljava/lang/String;
RETURN
MAXSTACK = 3
MAXLOCALS = 0
// access flags 0x19
public final static Lcom/hoge/Constants$Companion; Companion
// access flags 0x1019
public final static synthetic access$getNAME$cp()Ljava/lang/String;
@Lorg/jetbrains/annotations/NotNull;() // invisible
L0
LINENUMBER 6 L0
GETSTATIC com/hoge/Constants.NAME : Ljava/lang/String;
ARETURN
L1
MAXSTACK = 1
MAXLOCALS = 0
@Lkotlin/Metadata;(mv={1, 1, 6}, bv={1, 0, 1}, k=1, d1={"\u0000\u000c\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\u0008\u0003\u0018\u0000 \u00032\u00020\u0001:\u0001\u0003B\u0005\u00a2\u0006\u0002\u0010\u0002\u00a8\u0006\u0004"}, d2={"Lcom/hoge/Constants;", "", "()V", "Companion", "production sources for module hoge"})
// access flags 0x19
public final static INNERCLASS com/hoge/Constants$Companion com/hoge/Constants Companion
// compiled from: Constants.kt
}
// ================com/hoge/Constants$Companion.class =================
// class version 50.0 (50)
// access flags 0x31
public final class com/hoge/Constants$Companion {
// access flags 0x11
public final getNAME()Ljava/lang/String;
@Lorg/jetbrains/annotations/NotNull;() // invisible
L0
LINENUMBER 9 L0
INVOKESTATIC com/hoge/Constants.access$getNAME$cp ()Ljava/lang/String;
ARETURN
L1
LOCALVARIABLE this Lcom/hoge/Constants$Companion; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 0x2
private <init>()V
L0
LINENUMBER 8 L0
ALOAD 0
INVOKESPECIAL java/lang/Object.<init> ()V
RETURN
L1
LOCALVARIABLE this Lcom/hoge/Constants$Companion; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 0x1001
public synthetic <init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
L0
LINENUMBER 8 L0
ALOAD 0
INVOKESPECIAL com/hoge/Constants$Companion.<init> ()V
RETURN
L1
LOCALVARIABLE this Lcom/hoge/Constants$Companion; L0 L1 0
LOCALVARIABLE $constructor_marker Lkotlin/jvm/internal/DefaultConstructorMarker; L0 L1 1
MAXSTACK = 1
MAXLOCALS = 2
@Lkotlin/Metadata;(mv={1, 1, 6}, bv={1, 0, 1}, k=1, d1={"\u0000\u0014\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\u0008\u0002\n\u0002\u0010\u000e\n\u0002\u0008\u0003\u0008\u0086\u0003\u0018\u00002\u00020\u0001B\u0007\u0008\u0002\u00a2\u0006\u0002\u0010\u0002R\u0014\u0010\u0003\u001a\u00020\u0004X\u0086D\u00a2\u0006\u0008\n\u0000\u001a\u0004\u0008\u0005\u0010\u0006\u00a8\u0006\u0007"}, d2={"Lcom/hoge/Constants$Companion;", "", "()V", "NAME", "", "getNAME", "()Ljava/lang/String;", "production sources for module hoge"})
// access flags 0x19
public final static INNERCLASS com/hoge/Constants$Companion com/hoge/Constants Companion
// compiled from: Constants.kt
}
色々書かれてありますが、NAMEの部分を見てみると、Companionクラスの中のgetNAME()
というメソッドを通してNAMEにアクセスしていることが分かります。
javaからだと、Constants.Companion.getNAME()
でNAMEにアクセスできます。
constをつけて定数を定義した場合
class Constants {
companion object {
const val NAME = "taku"
}
}
これをバイトコードで見てみると、
// ================com/hoge/Constants.class =================
// class version 50.0 (50)
// access flags 0x31
public final class com/hoge/Constants {
// access flags 0x1
public <init>()V
L0
LINENUMBER 6 L0
ALOAD 0
INVOKESPECIAL java/lang/Object.<init> ()V
RETURN
L1
LOCALVARIABLE this Lcom/hoge/Constants; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 0x19
public final static Ljava/lang/String; NAME = "taku"
@Lorg/jetbrains/annotations/NotNull;() // invisible
// access flags 0x8
static <clinit>()V
NEW com/hoge/Constants$Companion
DUP
ACONST_NULL
INVOKESPECIAL com/hoge/Constants$Companion.<init> (Lkotlin/jvm/internal/DefaultConstructorMarker;)V
PUTSTATIC com/hoge/Constants.Companion : Lcom/hoge/Constants$Companion;
RETURN
MAXSTACK = 3
MAXLOCALS = 0
// access flags 0x19
public final static Lcom/hoge/Constants$Companion; Companion
@Lkotlin/Metadata;(mv={1, 1, 6}, bv={1, 0, 1}, k=1, d1={"\u0000\u000c\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\u0008\u0003\u0018\u0000 \u00032\u00020\u0001:\u0001\u0003B\u0005\u00a2\u0006\u0002\u0010\u0002\u00a8\u0006\u0004"}, d2={"Lcom/hoge/Constants;", "", "()V", "Companion", "production sources for module hoge"})
// access flags 0x19
public final static INNERCLASS com/hoge/Constants$Companion com/hoge/Constants Companion
// compiled from: Constants.kt
}
// ================com/hoge/Constants$Companion.class =================
// class version 50.0 (50)
// access flags 0x31
public final class com/hoge/Constants$Companion {
// access flags 0x2
private <init>()V
L0
LINENUMBER 7 L0
ALOAD 0
INVOKESPECIAL java/lang/Object.<init> ()V
RETURN
L1
LOCALVARIABLE this Lcom/hoge/Constants$Companion; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 0x1001
public synthetic <init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
L0
LINENUMBER 7 L0
ALOAD 0
INVOKESPECIAL com/hoge/Constants$Companion.<init> ()V
RETURN
L1
LOCALVARIABLE this Lcom/hoge/Constants$Companion; L0 L1 0
LOCALVARIABLE $constructor_marker Lkotlin/jvm/internal/DefaultConstructorMarker; L0 L1 1
MAXSTACK = 1
MAXLOCALS = 2
@Lkotlin/Metadata;(mv={1, 1, 6}, bv={1, 0, 1}, k=1, d1={"\u0000\u0012\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\u0008\u0002\n\u0002\u0010\u000e\n\u0000\u0008\u0086\u0003\u0018\u00002\u00020\u0001B\u0007\u0008\u0002\u00a2\u0006\u0002\u0010\u0002R\u000e\u0010\u0003\u001a\u00020\u0004X\u0086T\u00a2\u0006\u0002\n\u0000\u00a8\u0006\u0005"}, d2={"Lcom/hoge/Constants$Companion;", "", "()V", "NAME", "", "production sources for module hoge"})
// access flags 0x19
public final static INNERCLASS com/hoge/Constants$Companion com/hoge/Constants Companion
// compiled from: Constants.kt
}
constをつけた場合には、Companionクラスは存在していますが、getNAMEメソッドがなくなって、Companionクラスを介さずに直接NAMEにアクセスすることができます。
javaからだと、Constants.NAME
でNAMEにアクセスできます。
まとめ
- constをつけるとgetXXX()がなくなるのでメソッド数が減る。
- constをつけるとgetXXX()メソッドを一つ挟まずに直接変数にアクセスする。
constがつけれるときはつけたほうが良さそう。