var str:String是可变的还是不可变的?

我已经在Kotlin中声明了一个String变量。

var str: String

Kotlin文件与可变性概念相矛盾。 按照文档… var是可变的。 var是可变的

但是对于字符串,它定义为不可变的。 字符串是不可变的

所以请澄清矛盾

实际上,String variable是可变的,但是String Value是不可变的。

感谢@ cricket_007

让我深刻地描述当你声明变量时发生的事情。

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

在这里输入图像描述

如上图所示和声明。

字符串池是堆内存中的特殊存储区域。

当一个string is created并且如果该字符串already exists于池中,则existing string will be returned的引用,而不是创建一个新对象并返回其引用。

如果字符串不是不可变的,用一个引用改变字符串会导致其他引用的值错误。

现在我们可以使用这个变量,上面我们的例子Value Assign to Variable String1

也可以改变价值

 string1.renameTo("Hi This Is Test") 

那么在内存后面发生了什么?
– >是的,
如果 “Hi This Is Test”这个字符串可用,它将返回一个对“ string1 ”的引用
否则它创建新的空间并给参考“ string1

其实,这就是为什么字符串被称为不可变的。

参考 – 链接

我不喜欢写文档的方式,但实际上没有矛盾。 他们正在使用可变的单词,以便在程序符号对象之间进行比较,这些并不十分有用。

var关键字声明的变量是可重新分配的,而用val关键字声明的变量不是。

一个字符串是一个不可变的对象类型,一旦创建就不能改变。

一个变量是否可以重新分配以及它指向的对象是不可变的是两个不同的事情。

这是一个例子:

 class Person(var name: String) val fred = Person("Fred") fred.name = "Barry" // fred is not immutable fred = Person("Barry") // ERROR Val cannot be reassigned 

所以要用文件的方式使用mutable,仅仅因为一个符号被声明为一个val就不会使它指向不可变的对象

@Frank的一个很好的例子 。 这让我更清楚,文件说了什么。

文档的第一部分说:

Kotlin的课程可以有属性。 这些可以声明为可变的,使用var关键字或使用val关键字只读。

现在,第二部分说:

字符串由String类型表示。 字符串是不可改变的。

这两个都是我的看法。

基于弗兰克的例子,我们再举一个例子。

 data class User(var name: String, var email:String) var user1 = User("Foo","foo@bar.com") // user1 is mutable and object properties as well val user2 = User("Bar","bar@foo.com") // user2 is immutable but object's properties are mutable 

现在,考虑属性user1 。 它是可变的,因为它是用关键字var声明的。 用户对象也分配给它。

但是user2属性是不可变的。 你不能改变分配的对象。 但是,对象本身具有可变属性。 所以属性可以通过user2.name = "Foo"来改变。

现在改变一下例子,使用户属性不可变。

 data class User(val name: String, val email:String) var user1 = User("Foo","foo@bar.com") // user1 is mutable and object properties are not val user2 = User("Bar","bar@foo.com") // user2 is immutable and object's properties are also immutable 

在这里,用户的属性是不可变的。 所以, user1是可变的,你可以分配另一个对象。 但是这些属性是不可改变的。 所以user1 = User("New Foo","newfoo@bar.com")将工作。 但是在分配一个对象User之后,你不能改变它的属性,因为它们是不可变的。

现在我们来看一个String类型的例子。

 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) 

正如弗兰克所说,

只是因为一个符号被声明为一个val不会使它指向不可变的对象。

我最后的分钱:

字符串对象是不可变的,因为它不能被改变。 但是这个不可变的String对象可以赋值给一个可变属性 ,可以用不同的String对象来重新赋值。 这就是var关键字的作用。 使属性可变。 但是它指向的对象可以是可变的或不可变的。

矛盾是什么? 一个字符串是只读的。 就像Java一样,你不能设置a[i] = 'x' ,任何字符串替换方法都会返回新的字符串等,所以不可变。 这一点是为了阐明一个var String类型的功能

var和val之间的区别可以与Java中的final变量相关联。 你可以做一个final String常量,或者你可以有一个普通的String对象

在Kotlin / Java中,对象的行为并不取决于用来访问它的引用类型。 一切都(可能)在堆中,所以任何属性只是对象的引用(又名链接)。

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

在上面的代码片段中,只有一个不可变的字符串str ,并且ab引用它。 无论您使用什么参考,都无法更改字符串,可变或不可变。 但是你可以改变可变引用本身来指向另一个(不可变的)字符串:

 b = "World" 

就个人而言,我觉得用Java来思考valvar之间的区别是比较容易的。 val会与final修饰符对应一个变量,这意味着它只能被赋值一次,而var只是该修饰符不存在而可以重新赋值。

对象本身仍然可以是可变的或不可变的。 这里的可变性是指变量本身。