简体   繁体   中英

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.

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?

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?

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". That string is made up of the value of the content of your variable aa .

If k were to change with mutation to aa would demand a few things:

  • 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.

Kotlin doesn't have "lazy evaluation", and var k = "$aa" is not a function call, it's just an evaluation and instantly assignment. Then when you ask var k = "$aa" , "$aa" is evaluated, and k is assigned.

After that, k will "forget" about how it was evaluated, so you do aa = aa + 5 will have no effect on 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".

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. 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:

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:

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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