建议如何在Kotlin中创建常量?命名规则是什么?我在文档里没有找到。
companion object {
//1
val MY_CONST = "something"
//2
const val MY_CONST = "something"
//3
val myConst = "something"
}
或者…?
建议如何在Kotlin中创建常量?命名规则是什么?我在文档里没有找到。
companion object {
//1
val MY_CONST = "something"
//2
const val MY_CONST = "something"
//3
val myConst = "something"
}
或者…?
当前回答
如果你把const val valName = valValue放在类名之前,这样就会创建一个
public static final YourClass。Kt会有公共的静态最终值。
科特林:
const val MY_CONST0 = 0
const val MY_CONST1 = 1
data class MyClass(var some: String)
Java反编译:
public final class MyClassKt {
public static final int MY_CONST0 = 0;
public static final int MY_CONST1 = 1;
}
// rest of MyClass.java
其他回答
class Myclass {
companion object {
const val MYCONSTANT = 479
}
}
你有两个选择,你可以使用const关键字或使用@JvmField,这使它成为java的静态最终常量。
class Myclass {
companion object {
@JvmField val MYCONSTANT = 479
}
}
如果您使用@JvmField注释,那么在它编译之后,常量就会以java中调用它的方式为您放入。 就像你在java中调用它一样,当你在代码中调用同伴常量时,编译器会为你替换它。
但是,如果使用const关键字,则常量的值将内联。内联是指在编译后使用实际值。
所以总结一下编译器将为你做什么:
//so for @JvmField:
Foo var1 = Constants.FOO;
//and for const:
Foo var1 = 479
我认为这将是把一个包的所有常量放在同一个文件中的最好方法,正如在其他答案中提到的,这避免了创建伴侣对象,这使得这个性能和非常类似于Java constants类。
class Constants {
object Analytics {
const val PROJECT_OPEN = "project_open"
const val PROJECT_CLOSE = "project_close"
}
object HTTP {
const val BASE_URL = "x.y.com"
}
object DBConst {
const val TABLE_NAME = "abc"
}
}
这可以从这样的代码中引用,使其非常结构化。
Constants.Analytics.PROJECT_OPEN
Constants.HTTP.BASE_URL
Constants.DBConst.TABLE_NAME
首先,Kotlin中常量的命名约定与java中相同(例如:MY_CONST_IN_UPPERCASE)。
我应该如何创建它?
1. 作为顶级值(推荐)
你只需要把const放在类声明的外面。
两种可能:在类文件中声明const(你的const与你的类有明确的关系)
private const val CONST_USED_BY_MY_CLASS = 1
class MyClass {
// I can use my const in my class body
}
创建一个专用的常量。在这里你想要在你的项目中广泛使用你的const文件:
package com.project.constants
const val URL_PATH = "https:/"
然后你只需要把它导入到你需要的地方:
import com.project.constants
MyClass {
private fun foo() {
val url = URL_PATH
System.out.print(url) // https://
}
}
2. 在伴生对象(或对象声明)中声明它
这就不那么干净了,因为在底层,当字节码生成时,会创建一个无用的对象:
MyClass {
companion object {
private const val URL_PATH = "https://"
const val PUBLIC_URL_PATH = "https://public" // Accessible in other project files via MyClass.PUBLIC_URL_PATH
}
}
更糟糕的是,如果你将它声明为val而不是const(编译器将生成一个无用的对象+一个无用的函数):
MyClass {
companion object {
val URL_PATH = "https://"
}
}
注意:
在kotlin中,const只能保存原始类型。如果希望将调用函数的结果分配给它,则需要添加@JvmField注释。在编译时,它将被转换为一个公共静态final变量。但是它比原始类型要慢。尽量避免。
@JvmField val foo = Foo()
在Kotlin中有几种定义常量的方法,
使用伴随对象
companion object {
const val ITEM1 = "item1"
const val ITEM2 = "item2"
}
你可以在任何类中使用上面的同伴对象块,并在这个块中定义你的所有字段。但是这种方法有一个问题,文档说,
尽管伴随对象的成员看起来像其他语言中的静态成员,但在运行时,它们仍然是实际对象的实例成员,并且可以实现接口。
当你使用同伴对象创建常量,并看到反编译的字节码时,你会像下面这样:
ClassName.Companion Companion = ClassName.Companion.$$INSTANCE;
@NotNull
String ITEM1 = "item1";
@NotNull
String ITEM2 = "item2";
public static final class Companion {
@NotNull
private static final String ITEM1 = "item1";
@NotNull
public static final String ITEM2 = "item2";
// $FF: synthetic field
static final ClassName.Companion $$INSTANCE;
private Companion() {
}
static {
ClassName.Companion var0 = new ClassName.Companion();
$$INSTANCE = var0;
}
}
从这里你可以很容易地看到文档说了什么,即使伴随对象的成员看起来像其他语言中的静态成员,在运行时,它们仍然是实际对象的实例成员。
现在有另一种方法,我们不需要像下面这样使用同伴对象,
object ApiConstants {
val ITEM1: String = "item1"
}
同样,如果你看到上述片段的字节代码的反编译版本,你会发现这样的东西,
public final class ApiConstants {
private static final String ITEM1 = "item1";
public static final ApiConstants INSTANCE;
public final String getITEM1() {
return ITEM1;
}
private ApiConstants() {
}
static {
ApiConstants var0 = new ApiConstants();
INSTANCE = var0;
CONNECT_TIMEOUT = "item1";
}
}
现在,如果您看到上面的反编译代码,它正在为每个变量创建get方法。这个get方法根本不是必需的。
要摆脱这些get方法,你应该在val之前使用const,如下所示:
object ApiConstants {
const val ITEM1: String = "item1"
}
现在,如果您看到上述代码片段的反编译代码,您会发现它更容易阅读,因为它为您的代码进行了最少的后台转换。
public final class ApiConstants {
public static final String ITEM1 = "item1";
public static final ApiConstants INSTANCE;
private ApiConstants() {
}
static {
ApiConstants var0 = new ApiConstants();
INSTANCE = var0;
}
}
所以这是创建常数的最好方法。
像val一样,用const关键字定义的变量是不可变的。这里的区别在于,const用于编译时已知的变量。
声明一个变量const很像在Java中使用static关键字。
让我们看看如何在Kotlin中声明一个const变量:
const val COMMUNITY_NAME = "wiki"
用Java编写的类似代码是:
final static String COMMUNITY_NAME = "wiki";
加上上面的答案-
@JvmField可以用来指示Kotlin编译器不生成 getter /setter,并将其公开为字段。
@JvmField
val COMMUNITY_NAME = "Wiki"
静态字段
在命名对象或伴生对象中声明的Kotlin属性 将有静态支持字段,无论是在该命名对象或 包含伴生对象的类。
通常这些字段是私有的,但它们可以通过以下方式之一公开:
@JvmField注释; lateinit修饰语; const修饰符。
更多详情请访问:https://kotlinlang.org/docs/reference/java-to-kotlin-interop.html#instance-fields