如果一个字符串是不可变的,那么这是否意味着...(假设使用JavaScript)
var str = 'foo';
alert(str.substr(1)); // oo
alert(str); // foo
这是否意味着当调用字符串的方法时,它将返回修改后的字符串,但不会改变初始字符串?
如果字符串是可变的,那么第二个alert()
也会返回oo
吗?
如果一个字符串是不可变的,那么这是否意味着...(假设使用JavaScript)
var str = 'foo';
alert(str.substr(1)); // oo
alert(str); // foo
这是否意味着当调用字符串的方法时,它将返回修改后的字符串,但不会改变初始字符串?
如果字符串是可变的,那么第二个alert()
也会返回oo
吗?
这意味着,一旦您实例化对象,就无法更改其属性。在第一个警报中,您没有更改foo
。您正在创建一个新字符串。这就是为什么在第二个警报中它将显示"foo"而不是"oo"。
这是不是意味着,在字符串上调用方法会返回修改后的字符串,但不会更改初始字符串?
是的。一旦创建了字符串,就不能更改它。现在这并不意味着您不能将一个新的字符串对象分配给str
变量。只是您不能更改当前由str
引用的对象。
如果字符串是可变的,这是否意味着第二个
alert()
也会返回"oo"?
从技术上讲,不会,因为substring
方法返回一个新字符串。使一个对象可变并不会改变该方法。使其可变意味着从技术上讲,您可以使其如此,以便substring
更改原始字符串而不是创建一个新字符串。
在更低层面上,不可变性意味着存储字符串的内存不会被修改。一旦你创建了一个字符串 "foo"
,会分配一些内存来存储值 "foo"
,这个内存不会被更改。如果你使用substr(1)
修改字符串,那么将创建一个新的字符串,并分配一个不同的内存部分来存储 "oo"
。现在你有两个字符串在内存中,"foo"
和"oo"
。即使你不再使用 "foo"
,它也会一直保留,直到被垃圾回收。
这也是字符串操作相对较慢的原因之一。
Immutable(不可变)意味着不能被改变或修改。
当你给一个字符串赋值时,新的值是从头开始创建的,而不是替换原有的值。所以每次将一个新值赋给相同的字符串时,都会创建一个副本。因此实际上,你从未改变过原始值。
String lit1 = "foo";
String lit2 = "foo";
String cons = new String("foo");
System.out.println(lit1 == lit2); // true
System.out.println(lit1 == cons); // false
System.out.println(lit1.equals(cons)); // true
在上面的代码中,lit1
和lit2
都使用相同的字符串字面量构造,所以它们指向相同的内存地址;lit1 == lit2
的结果为true
,因为它们恰好是同一个对象。cons
是使用类构造函数构造的。尽管参数是相同的字符串常量,但构造函数为cons
分配了新的内存,这意味着cons
不是与lit1
和lit2
相同的对象,尽管它们包含相同的数据。equals
方法将返回true。可变性的教科书定义是可以改变或修改的。在编程中,我们使用这个词来表示那些状态允许随时间改变的对象。不可变值则完全相反 - 在它被创建后,它永远不会改变。
如果这看起来很奇怪,让我提醒你,我们经常使用的许多值实际上是不可变的。
var statement = "I am an immutable value";
var otherStr = statement.slice(8, 17);
Immutable指的是值不能被改变。一旦创建了一个字符串对象,它就是不可修改的。如果您要求一个字符串的子串,将会创建一个具有所请求部分的新字符串。
在操作字符串时使用StringBuffer可以使操作更高效,因为StringBuffer将字符串存储在字符数组中,并使用变量来保存字符数组的容量和长度(以字符数组形式的字符串)。
理解这个概念的一种方法是看看JavaScript如何处理所有对象,即通过引用。这意味着所有对象在实例化后都是可变的,这意味着您可以添加具有新方法和属性的对象。这很重要,因为如果您希望对象是不可变的,则对象在实例化后不能更改。
可变性的教科书定义是易于改变或修改。在编程中,我们使用这个词来表示那些状态允许随时间改变的对象。不可变值则完全相反 - 在创建后,它永远不会改变。
如果这看起来很奇怪,让我提醒你,我们经常使用的许多值实际上都是不可变的。
var statement = "我是一个不可变的值"; var otherStr = statement.slice(8, 17);
我想没有人会感到惊讶,得知第二行代码并没有以任何方式改变语句中的字符串。事实上,没有任何字符串方法会改变它们所操作的字符串,它们都会返回新的字符串。原因是字符串是不可变的 - 它们不能改变,我们只能创建新的字符串。
字符串不是内置于JavaScript中的唯一不可变值。数字也是不可变的。你能想象出一个环境,在这个环境中计算表达式2 + 3会改变数字2的含义吗?这听起来很荒谬,然而我们经常这样做,处理对象和数组。
试一下这个:
let string = "name";
string[0] = "N";
console.log(string); // name not Name
string = "Name";
console.log(string); // Name
因此,这意味着字符串是不可变的但不是常量,简单地说,重新赋值是可以发生的,但不能改变某些部分。