我在Kotlin中声明了一个String变量。
var str: String
Kotlin文件与可变性概念相矛盾。 根据文件...... var是可变的。
但是对于String,它定义为不可变的。
所以请澄清矛盾......
答案 0 :(得分:8)
我不喜欢写文档的方式,但实际上并没有矛盾。他们使用 mutable 这个词,其方式是邀请程序符号和对象之间的比较,但这并不是很有帮助。
var
关键字声明的变量是可重新分配的,而使用val
关键字声明的变量不是。
字符串是一种不可变对象类型,一旦创建就无法更改。
变量是否可重新分配以及它指向的对象是 immutable 是两回事。
以下是一个例子:
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
不会使对象指向不可变。
答案 1 :(得分:6)
实际上,String variable
是可变的,但String Value
是不可变的。
赞赏@ cricket_007
让我深入描述当您声明变量时背后发生的事情。
val string1 = "abcd"
val string2 = "abcd"
如上图所示和声明。
-String pool是堆内存中的特殊存储区域。
- 当string is created
和池中的字符串already exists
时,existing string will be returned
的引用,而不是创建新对象并返回其引用。
- 如果字符串不是不可变的,用一个引用更改字符串将导致其他引用的值错误。
现在我们可以使用此变量,现在我们的示例值分配给变量 String1 。
我们也可以更改值
string1.renameTo("Hi This Is Test")
那么在记忆中会发生什么呢?
- >是,
如果 "嗨这是测试" 此字符串可用,它将返回对" string1 &#34的引用;
其他它创建新空间并提供参考" string1 "
实际上,这就是为什么String称为不可变的。
参考 - Link
答案 2 :(得分:4)
@Frank的excellent example。它让我更清楚,文档说的是什么。
文档的第一部分说:
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
声明的。并且User对象也分配给它。
但user2
属性是不可变的。您无法将指定的对象更改为它。但是Object本身具有可变属性。因此,属性可以按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对象可以分配给可变的属性,其中 可以使用不同的String对象重新分配。那是什么
var
关键字确实如此。使财产变得可变。但对象呢 指向可以是可变的或不可变的。
答案 3 :(得分:3)
矛盾是什么?字符串是只读的。就像Java一样,你不能设置a[i] = 'x'
,任何字符串替换方法都会返回新的字符串等。因此,不可变。这一点是为了阐明var
字符串类型
var和val之间的差异可以与Java中的final
变量相关联。您可以设置final String
常量,也可以设置常规String
对象
答案 4 :(得分:0)
在Kotlin / Java中,对象的行为不取决于您用来访问它的引用类型。一切都(可能)在堆中,因此任何属性都只是对象的引用(a.k.a.链接)。
val str = "Hello"
val a = str
var b = str
在上面的代码段中,只有一个不可变字符串str
,而a
和b
都引用它。无论您使用什么引用,可变或不可变,您都无法更改字符串。但是您可以将可变引用本身更改为指向另一个(不可变)字符串:
b = "World"
答案 5 :(得分:0)
就个人而言,我发现在Java方面考虑List<Main> mainList = ...
var flatList = (
from main in mainList
from owner in main.Owners
select new FlatList {
Id = main.Id, Name = main.Name,
OwnerId = owner.Id, OwnerName = owner.Name
}).ToList();
和val
之间的区别更容易。 var
将对应于具有val
修饰符的变量,这意味着它只能分配一次,而final
只是缺少该修饰符,因此可以重新分配。
对象本身仍然可以是可变的或不可变的。这里的可变性是指变量本身。