建议如何在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"
}
或者…?
当前回答
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
其他回答
在Kotlin中,如果你想创建在类中使用的局部常数,那么你可以像下面这样创建它
val MY_CONSTANT = "Constants"
如果你想在kotlin中创建一个公共常量,就像在java中创建public static final一样,你可以像下面这样创建它。
companion object{
const val MY_CONSTANT = "Constants"
}
在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;
}
}
所以这是创建常数的最好方法。
对于基元和字符串:
/** The empty String. */
const val EMPTY_STRING = ""
其他情况:
/** The empty array of Strings. */
@JvmField val EMPTY_STRING_ARRAY = arrayOfNulls<String>(0)
例子:
/*
* Copyright 2018 Vorlonsoft LLC
*
* Licensed under The MIT License (MIT)
*/
package com.vorlonsoft.android.rate
import com.vorlonsoft.android.rate.Constants.Utils.Companion.UTILITY_CLASS_MESSAGE
/**
* Constants Class - the constants class of the AndroidRate library.
*
* @constructor Constants is a utility class and it can't be instantiated.
* @since 1.1.8
* @version 1.2.1
* @author Alexander Savin
*/
internal class Constants private constructor() {
/** Constants Class initializer block. */
init {
throw UnsupportedOperationException("Constants$UTILITY_CLASS_MESSAGE")
}
/**
* Constants.Date Class - the date constants class of the AndroidRate library.
*
* @constructor Constants.Date is a utility class and it can't be instantiated.
* @since 1.1.8
* @version 1.2.1
* @author Alexander Savin
*/
internal class Date private constructor() {
/** Constants.Date Class initializer block. */
init {
throw UnsupportedOperationException("Constants.Date$UTILITY_CLASS_MESSAGE")
}
/** The singleton contains date constants. */
companion object {
/** The time unit representing one year in days. */
const val YEAR_IN_DAYS = 365.toShort()
}
}
/**
* Constants.Utils Class - the utils constants class of the AndroidRate library.
*
* @constructor Constants.Utils is a utility class and it can't be instantiated.
* @since 1.1.8
* @version 1.2.1
* @author Alexander Savin
*/
internal class Utils private constructor() {
/** Constants.Utils Class initializer block. */
init {
throw UnsupportedOperationException("Constants.Utils$UTILITY_CLASS_MESSAGE")
}
/** The singleton contains utils constants. */
companion object {
/** The empty String. */
const val EMPTY_STRING = ""
/** The empty array of Strings. */
@JvmField val EMPTY_STRING_ARRAY = arrayOfNulls<String>(0)
/** The part 2 of a utility class unsupported operation exception message. */
const val UTILITY_CLASS_MESSAGE = " is a utility class and it can't be instantiated!"
}
}
}
在Kotlin中声明常量不需要类、对象或伴生对象。您可以声明一个包含所有常量的文件(例如constants。或者你也可以把它们放在任何现有的Kotlin文件中),并直接在文件中声明常量。编译时已知的常量必须用const标记。
所以,在这种情况下,它应该是:
const val MY_CONST = "something"
然后你可以导入常量使用:
import package_name.MY_CONST
你可以参考这个链接
Something that isn't mentioned in any of the answers is the overhead of using companion objects. As you can read here, companion objects are in fact objects and creating them consumes resources. In addition, you may need to go through more than one getter function every time you use your constant. If all that you need is a few primitive constants on a few instances of your class, you'll probably just be better off using val to get a better performance and avoid the companion object. The trade off is higher memory consumption if you have many instances of your class so everyone should make their own decision.
TL,博士;文章:
使用伴侣对象实际上会将以下Kotlin代码:
class MyClass {
companion object {
private val TAG = "TAG"
}
fun helloWorld() {
println(TAG)
}
}
在这段Java代码中:
public final class MyClass {
private static final String TAG = "TAG";
public static final Companion companion = new Companion();
// synthetic
public static final String access$getTAG$cp() {
return TAG;
}
public static final class Companion {
private final String getTAG() {
return MyClass.access$getTAG$cp();
}
// synthetic
public static final String access$getTAG$p(Companion c) {
return c.getTAG();
}
}
public final void helloWorld() {
System.out.println(Companion.access$getTAG$p(companion));
}
}