Mohammad Derakhshan
Mohammad Derakhshan

Reputation: 1562

are string immutable in kotlin

I'm trying to learn Kotlin by reading its documentation. in the documentation there is a section about string. in that section it says:

Strings are immutable. Once you initialize a string, you can't change its value or assign a new value to it. All operations that transform strings return their results in a new String object, leaving the original string unchanged.

and tries to show that with an example:

fun main() {
    val str = "abcd"
    println(str.uppercase()) // Create and print a new String object
    println(str) // the original string remains the same
}

I have a problem with the part that says:

the value of strings can't change after initializing.

but when I change the val to var I easily can change the value of the string.

so what the documentation means by saying the value of string can't be changed? we know that val makes variables immutable, not just for strings.

Upvotes: 1

Views: 678

Answers (4)

Mark Bramnik
Mark Bramnik

Reputation: 42481

It looks like you’re confused by two different things:

  • reference management in Kotlin (var vs val)
  • String immutability

So to start with immutability: When you create an object it occupies some place in memory and contains “abcd” in your example.

The immutability means that you can’t change anything in this memory area, for example it’s impossible to make those bytes in memory to hold a string “abcE”. In general immutability means that you cannot change an internal state of the object after it has been created. This is a Design decisions of people who have developed a String class. They could easily provide API for changing the state (setters for example) but they chose to avoid doing so for many reasons which are beyond the scope of this question.

Now as for reference management: Usually you don’t just create a String (which is still immutable) but also maintain a reference to it so that you could address it from your program. There are two types of reference which confuse you. If you define a reference with a val keyword - this means that you won’t be able to “point” this reference to any other object, on the other hand, if you work with var keyword, its possible to assign another object to that reference:

val s = “abc”
s=“def” // impossible

var k = “abc”
k = “def” // ok

Upvotes: 4

Karunesh Palekar
Karunesh Palekar

Reputation: 2345

To explain in one sentence , String value remains immutable but the string variable is mutable .

Consider two string val a = "123" and val 2= "123" , then instead of creating two instances in the string pool , it creates only one instance and returns that instance to both the variables . String pool is an storage area in the heap memory. So hence ,when a string is created and if the string already exists in the pool, the reference of the existing string will be returned, instead of creating a new object and returning its reference. If string is not immutable, changing the string with one reference will lead to the wrong value for the other references. So when you change the value of one variable , it searches in the heap whether the value exist , if not it creates a new value in the heap else derives it from already existing one .

Upvotes: 1

Sweeper
Sweeper

Reputation: 271575

but when I change the val to var I easily can change the value of the string.

No, you cannot easily do that. Suppose you had:

var str = "foo"

This is not changing the value of the string "foo":

str = "bar"

You are just taking another instance of String and putting it inside the property str.

Notice that there is a difference between "the string" and "the property". "The string" refers to the instance of the String class that you created by doing "foo". That instance is immutable. You cannot do anything to it to make that same instance have a different sequence of characters than f, o, o. This is because the String class provides no public members that do this, and this is what the documentation was referring to when it says "String is immutable".

On the other hand, "the property" is the str that you declared by saying var str = ..., and it is mutable. It stores instances of Strings, and you can change what instances it stores. But you can't change the strings themselves, once they are created.

Compare this with lists. List is immutable, yet you can still do:

var myList: List<Int> = listOf(1, 2, 3)

Now suppose you want to remove all 3s in the list. You must create a new list:

// "filter" creates a new list
myList = myList.filter { it != 3 }

because List is immutable, and it does not have any methods that does this without creating a new list. If myList were a MutableList, however, you could have done:

// this does not create a new list
myList.removeIf { it == 3 }

There is no MutableString though :)

Upvotes: 7

TreffnonX
TreffnonX

Reputation: 2930

You are confusing the reference to the String with the instance of the String.

For a value to change, it's inner state must change. For a string object, once it is instantiated, it is never changed. However any references on that String may be reassigned another String instance, if they are themselves mutable.

val s = "My String"
var t = s
t = t + " Stuff"
println(s) // yields "My String"

Not only can no operator change the inner state of the String, but also no method on the String.

E.g. there exist languages, where you can do the following:

// note, this is pseudocode, and *not* kotlin semantics
final String someString = "Some String";
someString.cutFromEnd(" String");
println(someString); // could yield "Some" in some language.

Upvotes: 1

Related Questions