简体   繁体   English

为什么Kotlin中基于字符串的模板变量没有变化?

[英]Why doesn't a string based template variable change in Kotlin?

I know I can embed a var such as $aa in the string k expression, so line 3 displays the result 10. 我知道我可以在字符串k表达式中嵌入$aa ,因此第3行显示结果10。

I think the var k will change when I change the value of aa, so I think the line 5 will display the result 15, but in fact it displays 10. why? 我认为var k会在更改aa的值时发生变化,因此我认为第5行将显示结果15,但实际上它会显示10。为什么?

1  var aa=10
2  var k="$aa"
3  toast(k)  //This is  10

4  aa=aa+5
5  toast(k)   //This is  10, I think it should be 15

6  k="$aa"
7  toast(k)   //This is  15

Added Content 新增内容

I think the system will recalculate line 5 in the following code, so I think the new value aa 15 will be embed into k, but in fact , I get the result "10 bb", why? 我认为系统将在以下代码中重新计算第5行,因此我认为新值aa 15将嵌入到k中,但是实际上,我得到的结果是“ 10 bb”,为什么?

1 var aa=10
2 var k="$aa"
3 toast(k)    //This is  10

4  aa=aa+5
5  k=k+" bb"   //I think system will recalculate, so I think new value 15 will be embed into k
6  toast(k)   //This is  "10 bb", I think it should be "15 bb"

Strings are immutable and the reference k points to the specific string "10". 字符串是不可变的,引用k指向特定的字符串“ 10”。 That string is made up of the value of the content of your variable aa . 该字符串由变量aa的内容值组成。

If k were to change with mutation to aa would demand a few things: 如果k因突变而改变为aa则将需要一些注意事项:

  • Strings are partially mutable (which has significant speed impacts) 字符串部分可变(对速度产生重大影响)
  • every templated string would have to be recomputed on nearly every access 每个模板字符串几乎每次访问都必须重新计算
  • the scope of its creation would have to be closed around (see "closure") so the variables could be kept in reference 其创建范围必须封闭(请参见“封闭”),以便可以将变量保留在引用中
  • Subsequently, there would be phantom objects on the heap. 随后,堆上将有幻像对象。

That is a lot of computational overhead to display a string. 显示字符串的计算量很大。

To connect my two points, the last line of your example evaluates as you expect because your variable now points to a different string "15", because the value that the variable aa holds is different than previously at string construction time. 为了连接我的两点,示例的最后一行将按您期望的方式进行评估,因为变量现在指向不同的字符串“ 15”,因为变量aa持有的值与字符串构建时的值不同。

Kotlin doesn't have "lazy evaluation", and var k = "$aa" is not a function call, it's just an evaluation and instantly assignment. Kotlin没有“惰性求值”,并且var k = "$aa"不是函数调用,它只是求值并立即赋值。 Then when you ask var k = "$aa" , "$aa" is evaluated, and k is assigned. 然后,当您要求var k = "$aa" ,将评估"$aa"并分配k

After that, k will "forget" about how it was evaluated, so you do aa = aa + 5 will have no effect on k . 之后, k将“忘记”它的评估方式,因此您执行aa = aa + 5将对k无效。

For the "Added Content", regarding the same thought of above, k has been "forgot" how it was evaluated, assigning k = k + " bb" will just directly add the existing k (program level joining, not memory level concatenate) with string " bb", not re-evaluate k with "$aa". 对于“添加的内容”,基于上述相同的思想, k被“忘记”了如何评估,分配k = k + " bb"只会直接添加现有的 k (程序级联接,而不是存储级串联)字符串“ bb”,而不用“ $ aa”重新评估k

When you write down this line: 当您写下这一行时:

var k = "$aa"

... the string template on the right side of the assignment is evaluated immediately, and what gets assigned to k is the result of the template itself, the literal "10" string. ...赋值右侧的字符串模板将立即求值,分配给k是模板本身的结果,即文字"10"字符串。 That line is the same as if you had and of these in Java - and of course these won't change automatically later as aa gets updated either: 该行与您在Java中拥有的相同,并且当然不会随着aa的更新而自动更改:

String k = "" + aa;

String k = String.valueOf(aa);

String k = new StringBuilder().append(aa).toString();

To recompute this value every time, you could introduce a local function that you call over and over to create new strings every time, with aa 's then current value inserted into the template: 为了每次都重新计算该值,可以引入一个局部函数,每次调用它一次来创建新的字符串,并将aa的然后当前值插入模板:

var aa = 10
fun k() = "$aa" // same as: fun k(): String { return "$aa" }
println(k()) // 10

aa += 5
println(k()) // 15

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM