2017-06-17 66 views
11

我已經在Kotlin中聲明瞭一個String變量。var str:String是可變的還是不可變的?

var str: String

的科特林文件頂撞了可變性的概念。 根據文件... var是可變的。 var is mutable

但是對於字符串它定義爲不可變的。 String is immutable

所以請澄清矛盾......

回答

3

其實,字符串variable是可變的,但字符串Value是不可改變的。

與@ cricket_007欣賞

讓我深深的描述發生了什麼事背後當你聲明的變量。

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

enter image description here

如上所示圖像及聲明。

- 字符串池是堆中的一個特殊存儲區域

- 當一個string is created和如果字符串already exists在池中,引用existing string will be returned,而不是創建一個新的對象並返回其引用。

- 如果字符串不是不可變的,則用一個引用更改字符串將導致其他引用的值錯誤。

- 現在我們的例子賦值給變量String1中上面,現在我們可以使用這個變量。

我們也可以更改值

string1.renameTo("Hi This Is Test") 

因此,在後面的內存,會發生什麼?
- >是的,
如果「你好,這是測試」這個字符串可用時,它會返回一個參考「字符串1
其他它創建新的空間,提供參考。「STRING1

實際上,這就是爲什麼字符串被稱爲不可變的。

參考 - Link

+0

未解決的參考:renameTo。爲什麼? –

7

我不喜歡的文件寫入無論哪種方式,但在現實中並不矛盾。他們正在使用單詞mutable,以便在程序符號對象之間進行比較,這不是很有幫助。

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 

所以在文檔的方式做使用可變的,只是因爲符號被宣佈爲val不會使對象它指向不變。

+0

是的,但是可變的和可重新分配的一樣嗎? – RBK

+0

同意這兩個都是可重新分配的。但這並不意味着mutable =可重新分配。這就是我想澄清的 – RBK

+0

@FrankWilson極好的例子! – kirtan403

3

矛盾是什麼?一個字符串是隻讀的。就像Java一樣,你不能設置a[i] = 'x',任何字符串替換方法都會返回新的字符串等,所以不可變。這一點是爲了闡明var字符串類型的功能

var和val之間的差異可以與Java中的final變量相關聯。你可以使final String不變,或者你可以有一個正常的String對象

+0

一致認爲val和var與java的final ...有關但是是一個用var mutable或immutable聲明的String嗎? – RBK

+2

它總是不可改變的,正如我解釋過的,並且文檔中所說的......如果字符串是可變的,你期望做什麼? –

4

由@Frank的excellent example。這讓我更清楚,文件說的是什麼。

文件的第一部分說:在科特林

類可以有屬性。 這些可以聲明爲 mutable,使用var關鍵字或只讀使用val關鍵字。現在

,第二部分表示:

字符串由字符串類型表示。字符串是不可變的。

這兩個都是我的看法。

基於弗蘭克的例子,我們再舉一個例子。

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

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

val user2 = User("Bar","[email protected]") 
// 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","[email protected]") 
// user1 is mutable and object properties are not 

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

這裏,用戶的屬性是不可變的。所以,user1是可變的,你可以給它分配另一個對象。但屬性是不可改變的。所以user1 = User("New Foo","[email protected]")將工作。但是在分配一個對象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對象是不可改變的,因爲它不能被改變。但那 不可變的字符串對象可以分配給一個可變的屬性,其中 可以重新分配不同的字符串對象。這就是關鍵字 var。使屬性可變。但它指向的對象可以是可變的或不可變的。

0

在科特林/ Java的對象的行爲確實不取決於您用來訪問它的那種參考。一切都(可能)在堆中,所以任何屬性都只是對象的引用(a.k.a.鏈接)。

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

在片段上方僅存在一個不可變串str,並且兩個ab參考它。無論您使用什麼參考,都無法更改字符串,可變或不可變。但你可以改變的可變引用本身指向另一個(immutable)的字符串:

b = "World" 
0

就個人而言,我發現很容易想到在Java中的條款valvar之間的差異。 val將對應於帶有final修飾符的變量,這意味着它只能分配一次,而var只是該修飾符不存在並因此可重新分配。

對象本身仍然可以是可變的或不可變的。這裏的可變性是指變量本身。

相關問題