建议如何在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"
}
要么 ...?
Answers:
在Kotlin中,如果要创建应该在该类中使用的局部常量,则可以如下创建
val MY_CONSTANT = "Constants"
如果您想在kotlin中创建一个公共常量,例如public static final在Java中创建可以如下创建它。
companion object{
const val MY_CONSTANT = "Constants"
}
Constants.kt
或者如何使用?
companion object
我认为@piotrpo答案应该被接受
避免使用伴随对象。在引擎盖后面,创建了getter和setter实例方法,以使这些字段可访问。从技术上讲,调用实例方法比调用静态方法更昂贵。
public class DbConstants {
companion object {
val TABLE_USER_ATTRIBUTE_EMPID = "_id"
val TABLE_USER_ATTRIBUTE_DATA = "data"
}
而是在中定义常量 object
。
推荐做法:
object DbConstants {
const val TABLE_USER_ATTRIBUTE_EMPID = "_id"
const val TABLE_USER_ATTRIBUTE_DATA = "data"
}
并像这样全局访问它们:
DbConstants.TABLE_USER_ATTRIBUTE_EMPID
const val
在同伴的对象是比任何不同const val
在一个普通的对象(即你的例子之间的唯一差别似乎是你忽略const
的同伴对象的情况下-如果添加const
的例子应该具有相同的性能)
const val
s,则声明a companion object
是正确的。
首先, Kotlin中常量的命名约定与java中的约定相同(例如:MY_CONST_IN_UPPERCASE)。
您只需要将const 放在外面类声明。
两种可能性:在类文件中声明您的const(您的const与您的类有明确的关系)
private const val CONST_USED_BY_MY_CLASS = 1
class MyClass {
// I can use my const in my class body
}
创建一个专用的constants.kt文件,在其中存储这些全局const(在这里您想在整个项目中广泛使用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://
}
}
这是多少吸尘器因为罩下,当产生的字节代码,则创建一个无用对象:
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批注。在编译时,它将被转换为公共静态最终变量。但是它比原始类型要慢。尽量避免它。
@JvmField val foo = Foo()
可以(我认为应该)将编译时已知的值标记为常量。
命名约定应遵循Java的约定,并且在从Java代码中使用时应正确可见(无论如何,伴随对象很难实现)。
正确的常量声明是:
const val MY_CONST = "something"
const val MY_INT = 1
Naming conventions should follow Java ones
-为什么?
If in doubt, default to the Java Coding Conventions
您不需要在Kotlin中声明常量的类,对象或伴随对象。您可以只声明一个包含所有常量的文件(例如,Constants.kt,或者也可以将它们放在任何现有的Kotlin文件中),然后直接在文件中声明常量。编译时已知的常数必须标记为const
。
因此,在这种情况下,应为:
const val MY_CONST = "something"
然后可以使用以下命令导入常量:
import package_name.MY_CONST
你可以参考这个链接
如果你把 const val valName = valValue
的班级名称前面,则它将创建一个
public static final YourClass.Kt
将具有public static final
值。
科特林:
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
Kotlin静态和常数值与方法声明
object MyConstant {
@JvmField // for access in java code
val PI: Double = 3.14
@JvmStatic // JvmStatic annotation for access in java code
fun sumValue(v1: Int, v2: Int): Int {
return v1 + v2
}
}
随时随地访问价值
val value = MyConstant.PI
val value = MyConstant.sumValue(10,5)
与一样val
,用const
关键字定义的变量是不可变的。区别在于const
是用于编译时已知的变量。
声明变量const
很像使用static
在Java中关键字。
让我们看看如何在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
在任何答案中都没有提到的是使用的开销companion objects
。如您在这里所读,伴随对象实际上是对象,创建它们会消耗资源。另外,每次使用常量时,您可能需要使用多个getter函数。如果您只需要一些基本常量,则可能会更好,val
因为它可以获得更好的性能并避免使用companion object
。
TL; DR; 的文章:
使用随播对象实际上会变成这段代码
class MyClass {
companion object {
private val TAG = "TAG"
}
fun helloWorld() {
println(TAG)
}
}
变成这段代码:
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));
}
}
因此,尽量避免它们。
局部常数:
const val NAME = "name"
全局常数:
object MyConstants{
val NAME = "name"
val ID = "_id"
var EMAIL = "email"
}
访问MyConstants.NAME
您可以通过几种方法在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!"
}
}
}
public static final
Java中的字段相对应的内容,请const val
在您的伴随对象中使用。如果您想要一个private static final
字段和一个公共获取器,请val
在您的伴随对象中使用。