我在 Kotlin 中声明了一个字符串变量,如下所示。
var str: String
Kotlin 文档对于可变性的概念存在矛盾。
根据文档...
var
是可变的。
但是对于 String
,它定义为不可变的。
因此,请澄清这个矛盾...
我在 Kotlin 中声明了一个字符串变量,如下所示。
var str: String
Kotlin 文档对于可变性的概念存在矛盾。
根据文档...
var
是可变的。
但是对于 String
,它定义为不可变的。
因此,请澄清这个矛盾...
val string1 = "abcd"
val string2 = "abcd"
如上图所示并声明:
-字符串池是堆内存中的特殊存储区域。
-当创建一个字符串时,如果该字符串已经存在于池中,则返回现有字符串的引用,而不是创建新对象并返回其引用。
-如果字符串不是不可变的,则使用一个引用更改字符串会导致其他引用的值错误。
-现在我们将上面的例子值分配给变量String1,现在我们可以使用这个变量。
同时,我们也可以更改该值。
string1.renameTo("Hi This Is Test")
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
声明的symbol并不意味着它所指向的object是不可变的。
由@Frank提供的优秀示例让我更清楚地理解了文档所说的内容。
文档的第一部分说明:
Kotlin 中的类可以具有属性。这些属性可以使用 var 关键字声明为可变的,也可以使用 val 关键字声明为只读的。
现在,第二部分说明:
字符串由 String 类型表示。字符串是不可变的。
在我看来,这两者都是正确的。
基于 Frank 的例子,我们再举一个例子。
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
声明的,并且赋值了User对象。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 对象之后,您无法更改其属性,因为它们是不可变的。
现在,让我们来看一个字符串类型的例子。
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)
正如Frank所说:
仅仅因为一个符号被声明为val,并不意味着它指向的对象是不可变的。
我的最终观点:
字符串对象是不可变的,因为它不能被改变。但是这个不可变的字符串对象可以被赋值给一个可变的属性,这个属性可以被再次赋值为不同的字符串对象。这就是
var
关键字所做的。将属性变为可变的。但是它所指向的对象可以是可变或不可变的。
a [i] ='x'
,任何字符串替换方法都会返回新字符串等。因此,不可变。这一点是为了澄清 var
String类型的功能。 final
变量相关联。您可以创建一个 final String
常量,或者您可以拥有一个普通的 String
对象。就个人而言,我觉得更容易从Java的角度来思考val
和var
之间的区别。val
相当于一个带有final
修饰符的变量,这意味着它只能被赋值一次,而var
则没有这个修饰符,因此可以重新赋值。
对象本身仍然可以是可变或不可变的。这里的可变性是指变量本身。
val str = "Hello"
val a = str
var b = str
str
,而a
和b
都引用它。无论你使用可变或不可变的引用,你都不能改变这个字符串。但是,你可以更改可变引用本身,使其指向另一个(不可变的)字符串:b = "World"