什么可以用编译时常量(const val)表示?

时间:2017-07-05 09:08:53

标签: kotlin

编译时常量的文档列出了属性需要满足的三个要求,以便将其声明为const val。这些是:

  • 对象的顶级或成员
  • 使用String类型或基本类型
  • 初始化
  • 没有自定义getter

“没有自定义getter”的要求让我相信我不能在常量声明中使用任何函数,但似乎并非如此。这些编译:

const val bitmask = (5 shl 3) + 2
const val aComputedString = "Hello ${0x57.toChar()}orld${((1 shl 5) or 1).toChar()}"
const val comparedInt = 5.compareTo(6)
const val comparedString = "Hello".compareTo("World!")
const val toStringedInt = 5.compareTo(6).toString()
const val charFromString = "Hello World!".get(3)

但是,这些不会编译:

// An extension function on Int.
const val coercedInt = 3.coerceIn(1..5)

// Using operator syntax to call the get-function.
const val charFromString = "Hello World!"[3]

// An immediate type is not a primitive.
const val stringFromImmediateList = "Hello World!".toList().toString()

// Using a function defined by yourself.
fun foo() = "Hello world!"
const val stringFromFunction = foo()

编译时常量的确切规则是什么?

是否有我可以在编译时常量声明中使用的函数列表?

2 个答案:

答案 0 :(得分:3)

没有关于此的确切文档,但可以在编译器源here中找到可以在常量表达式中使用的函数列表。请注意,只有那些函数可以在kotlin包下定义的常量表达式中使用,在自定义重载操作符上编译器将报告错误。

答案 1 :(得分:1)

getter不是方法调用,实际上,它是属性声明的一部分,例如,下面的代码无法编译。

const val charFromString get() = "foo"
//                       ^--- const using getter can't be compiled

aComputedString常量使用字符串模板,就像java中的字符串连接一样,例如:

static final String aComputedString = "Hello " + ((char) 0x57) 
                                    + "orld" + ((char) ((1 << 5) | 1));

和opeartor针对原始类型进行了优化,因为它们在java中没有方法,例如:

const val longValue = 1.toLong();
// java
static final long longValue = (long) 1 ;

comparedString上方的代码可以正常使用kotlin.String而不是java.lang.String,因为映射类型kotlin.String也已优化,因为没有实现kotlin,如果你直接尝试java.lang.String,你可以获得预期的编译错误:

typealias JavaString = java.lang.String;
//         v--- error
const val comparedString = JavaString("Hello").compareTo("World!")

"Hello world!"[3]无法正常工作,因为indexed access operator的参数类型为vararg,因此编译器无法对其进行优化,因为它不是&get #39;知道将收到const val third = "Hello world!"[3] //error // will generate java code as static final String third = "Hello world!".charAt(3) // error 运算符的多少个参数,因此会使用List<KtExpression>列表动态调用它,例如:

const val comparison = "Hello" > "World";// ok

但是,对于具有基本类型的固定参数的运算符,将由编译器进行优化:

  

请注意,对于基本类型,这些操作以及所有其他操作都已优化,并且不会为它们引入函数调用的开销。

String.get(n)

kotlin.String可以正常工作,因为 const val third = "Hello".get(3) // ok // ^ // when you calling the `get` function, you never using `operator` at all. // it just a function invocation 是映射器类型,并且它没有实现,所以编译器知道如何计算它,例如:

String.toList()

const val无法分配给常量变量,因为它是一种扩展方法并且具有实现。和kotlin import glob #For any kind of file in that directory. for file in list(glob.glob("*")): # do your work #For specific kind of file in that directory. like all .py or .txt or .csv file.. etc. for file in list(glob.glob("*.file extension")): # do your work 仅支持原始类型字符串