Is var str: String mutable or immutable?

Is var str: String mutable or immutable?

I have declared a String variable in Kotlin as like.
var str: String
The Kotlin document contradict for mutability concept.
As per document...
var is mutable.

But for String it define as immutable.

So please clarify contradiction...


Answer 1:

Actually, String variable is mutable, but String Value is Immutable.

Appreciate with @cricket_007

Let me Describe deeply what happened behind When you declare variable.

val string1 = "abcd"  
val string2 = "abcd"

enter image description here

As Shown above image and Declaration.

-String pool is a special storage area in The Heap Memory.

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

-Now with above our example Value Assign to Variable String1 now we can use this variable.

also we can change the value

string1.renameTo("Hi This Is Test")

So What happen at behind in memory ?
if “Hi This Is Test” this string available it will return a reference to “string1
else it Create new space and give reference To “string1

Actually, that’s Why String called immutable.

Reference – Link

Answer 2:

I don’t like way the documentation is written either but there is no contradiction in reality. They are using the word mutable in a way that invites a comparison between program symbols and objects that is not very helpful.

A variable declared by the var keyword is reassignable whereas one declared with the val keyword is not.

A string is an immutable object type, once created it cannot be changed.

Whether a variable is reassignable and whether the object it points to is immutable are two different things.

Here’s an example:

class Person(var name: String)

val fred = Person("Fred") = "Barry" // fred is not immutable

fred = Person("Barry") // ERROR Val cannot be reassigned

So to use mutable in the way the documentation does, just because a symbol is declared a val does not make the object it points to immutable.

Answer 3:

An excellent example by @Frank. It makes me more clear, what the documentation said.

The first part of the documentation says:

Classes in Kotlin can have properties. These can be declared as
mutable, using the var keyword
or read-only using the val keyword.

Now, the second part says:

Strings are represented by the type String. Strings are immutable.

These both are true in my opinion.

Based on the Frank’s example, let’s take another example.

data class User(var name: String, var email:String)

var user1 = User("Foo","")  
// user1 is mutable and object properties as well

val user2 = User("Bar","")
// user2 is immutable but object's properties are mutable

Now, consider property user1. It is mutable as it is declared with keyword var. And also the User object assign to it.

But the user2 property is immutable. You can not change the assigned object to it. But the Object itself has mutable properties. So the properties can be changes by = "Foo".

Now changing the example a bit and making user properties immutable.

data class User(val name: String, val email:String)

var user1 = User("Foo","")  
// user1 is mutable and object properties are not

val user2 = User("Bar","")
// user2 is immutable and object's properties are also immutable

Here, User’s properties are immutable. So, user1 is mutable, you can assign another object to it. But the properties are immutable. So user1 = User("New Foo","") will work. But after assigning an object User, you can not change it’s properties, as they are immutable.

Now, let’s take an example with String type.

var str1 = "Bar"
// Here str1 (property) is mutable. So you can assign a different string to it. 
// But you can not modify the String object directly.
str1 = "Foo"  // This will work
str1[0] = 'B' // This will NOT work as The string object assigned to str1 is immutable

val str2 = "Foo"
// Here both str2 and the assigned object are immutable. (Just like Java final)

And as the Frank said,

just because a symbol is declared a val does not make the object it points to immutable.

My final cents:

String object is immutable, as it can not be changed. But that
immutable String object can be assigned to a mutable property, which
can be re-assigned with the different String Object. That is what
var keyword does. Making the property mutable. But the object it
points to can be mutable or immutable.

Answer 4:

What’s the contradiction? A string is read-only. Just as Java, you cannot set a[i] = 'x', any string replacement methods return new strings, etc. Therefore, not mutable. This point is made to clarify the functionality of a var String type

The difference between var and val can be associated with a final variable in Java. You can make a final String constant, or you can have a regular String object

Answer 5:

Personally, I find it easier to think about the difference between val and var in terms of Java. val would correspond to a variable with the final modifier, which means it can only be assigned once and var is just with that modifier absent and therefore reassignable.

The object themselves can still be either mutable or immutable. Mutability here refers to the variable itself.

Answer 6:

In Kotlin/Java an object’s behaviour does not depend on the kind of reference you use to access it. Everything is (potentially) in the heap, so any property is just a reference (a.k.a. link) to the object.

val str = "Hello"
val a = str
var b = str

In the snippet above there is only one immutable string str, and both a and b reference it. You can’t change the string, no matter what reference you use, mutable or immutable. But you can change the mutable reference itself to point to another (immutable) string:

b = "World"