字符串不变性在向开发人员解释字符串引用时扮演什么角色?
我经常以某种形式遇到以下问题(此处以伪代码提出):
String myString = "Hello"
someObject.stringProperty = myString
myString = "World"
为什么 someObject.stringProperty 现在不等于“World”?
以下陈述在解释为什么会出现这种情况时所扮演的角色似乎令人困惑:
字符串是不可变的
你觉得怎么样?
如果您认为该声明不适用,我会问您:在字符串可变的语言中,并且赋值运算符改变了它们的实际值(而不是简单地更改引用),会你的回答还有道理吗?
编辑:
好的,我觉得有必要澄清一些事情:
我对字符串、引用或赋值的工作原理并不感到困惑。我对这个话题非常清楚。我不是在问字符串是如何工作的。我问“字符串不变性在向开发人员解释字符串引用方面发挥什么作用”。我们可以跳过我一定感到困惑的人身攻击。
我正在为提出所引用问题的开发人员寻找逻辑上严格的答案,该答案不包含或预先假设字符串的不变性。
现有参数的分类:
字符串不变性与之无关,因为引用正在改变,而不是字符串的值
这个答案预先假设了我所询问的确切事实。赋值意味着引用的赋值而不是值的赋值
同样,这预先假设了我所询问的确切事实。对于字符串来说,没有理由一定是这种情况。出于性能和其他原因,字符串就是如此。
In one form or another I encounter the following question often (posed, here, in pseudo-code):
String myString = "Hello"
someObject.stringProperty = myString
myString = "World"
Why doesn't someObject.stringProperty now equal "World"?
There seems to be confusion about the role the following statement plays in the explanation of why this is the case:
Strings are Immutable
What do you think?
If you think the statement doesn't apply, I'd ask you this: In a language where strings were mutable, and the assignment operator mutated their actual value (instead of simply changing the reference), would your answer still make sense?
EDIT:
OK, I feel the need to clarify some things:
I'm not confused about how strings, references, or assignments work. I'm perfectly clear on this topic. I'm not asking how strings work. I'm asking "What role does string immutability play in the explaination of string references to developers". We can skip the Ad-Hominem attacks that I must be confused.
I'm looking for a logically rigorous answer for the developer asking the cited question which doesn't contain, or pre-suppose, the immutability of strings.
A categorization of the existing arguments:
String Immutability has nothing to do with it because the references are changing, not the values of the strings
This answer pre-supposes the exact fact I'm asking about.Assignment means assignment of references not assignment of values
Again, this pre-supposes the exact fact I'm asking about. There is no reason this must be the case for strings. It simply is the case for strings for performance and other reasons.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
发布评论
评论(3)
这是因为计算机编程中的等号更多的是赋值运算符,而不是“数学相等”条件。字符串不可变与它无关。这都是关于等号是“赋值”运算符而不是数学等价约束。
这意味着 A = B;且 B = C;并不意味着 A = C;
相反,这意味着
A 已被设置为引用 B 的值,因此 B 的值现在是 A 的值。
B 已被设置为引用 C 的值,因此 C 的值现在是 B 的值,但 A 的值保持不变
如果字符串不是不可变的
String myString = "Hello";
myString.replace(3, "p"); // replace starting at char #3 (the second 'l')
System.out.println(myString); // would print "Help"
但由于字符串是不可变的;
String myString = "Hello";
myString.replace(3, "p"); // returns a new string "help" which is not assigned to anything
// since the newly returned string was not assigned to anything, it was garbage collected
System.out.println(myString); // would print "Hello"
解释是这个例子与不变性无关。
您有两个变量最初包含相同的值,这对于字符串来说意味着它们指向内存中的同一个对象。然后更改其中一个变量的值并将其指向内存中的另一个对象。
这与说
int a = 4;
int b = a;
a = 5;
Or
string x = "Foo";
string y = x;
x = "Bar";
Or
Foo foo = new Foo() { Bar = 42 };
Foo otherFoo = foo;
foo = new Foo() { Bar = 17; }
没有什么不同。变量暂时引用相同的事物。它们并不是一直密不可分的。一旦你把一个人指向别的东西,他们的共性就结束了。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
陈述在解释中所起的作用取决于解释本身。它可能是有害的,也可能是有用的,这取决于其余的解释。
就我个人而言,直到解释的相当晚的时候我才会使用该声明(至少现在是这样)。字符串的不变性只是在某种程度上造成了阻碍——就像参数传递解释一样。我将首先使用可变类进行解释,如下所示:
在这里,我将解释
x
和y
就像一张写有房屋地址的纸。第二行中的赋值并不复制房屋 - 它复制房屋的地址。第三行的分配不会改变第一栋房子前门的颜色 - 它创建一个新房子,然后擦掉第一栋房子的地址纸 (x
),并写下新地址。这不会改变第一栋房子或第二张纸 (y
) 的任何内容。然后我会给出第二个例子:
这次只有一栋房子 - 如果我粉刷一栋房子的门,你用我之前给你的地址来看它,你会看到前门现在是红色的。
到目前为止,一切都很好。 现在我可以回到原来的例子并说它已经看起来像第一个房子片段而不是第二个,所以它的行为是相同的。然后我可以说,字符串不变性意味着您甚至无法编写看起来像第二个房子示例但使用字符串的代码。因此,字符串不变性不会立即与现有代码的解释相关,但它仍然会出现在同一个答案中。
(我还必须指出,虽然引用的行为类似于真实世界的地址,但我并不声称它们与“内存地址”或指针相同。它们不必是。我在使用该术语严格的与现实世界的类比,仅此而已。这是该示例的缺点,但我认为它不会造成太大伤害。)
然后我可能还会讨论值类型,并考虑会发生什么 。如果
House
是值类型,就会发生这种情况 - 并且不鼓励可变值类型。要知道我的答案是否仍然与具有可变字符串的语言相关,我们需要更多地了解字符串文字的行为方式。除了字符串的可变性之外,在所有方面都与 C# 相同的语言将是一种糟糕的语言,正如您可以写的那样:
这显然是不可取的,因此可能是字符串文字的行为就必须改变。您还讨论了赋值运算符的含义可能发生的变化,等等……如果不确切了解假设的语言的行为方式,就很难对它做出具体的陈述。
The role played by the statement in the explanation depends on the explanation itself. It could be harmful or useful, depending on the rest of the explanation.
Personally I wouldn't use that statement until fairly late in the explanation (at least these days). The immutability of strings just gets in the way somewhat - as it does with parameter passing explanations. I'd start with an explanation using a mutable class, like this:
Here I would explain that
x
andy
are like pieces of paper with the addresses of houses on. The assignment in the second line doesn't copy a house - it copies the address of a house. The assignment on the third line doesn't change the color of the front door on the first house - it creates a new house, then rubs out the address on the first piece of paper (x
), and writes the new address on. This doesn't change anything about the first house, or the second piece of paper (y
).I'd then produce a second example:
This time there's only one house - if I paint the door of a house and you come to see it with the address I'd given you earlier, you'll see the front door is now red.
So far, so good. Now I could go back to the original example and say that it already looks like the first house snippet rather than the second one, so it behaves the same way. I can then say that string immutability means you can't even write code that looks like the second house example but using strings. So string immutability wouldn't have been immediately relevant to the explanation of the existing code, but it would still have appeared in the same answer.
(I'd also have to point out that although references behave like real-world addresses, I'm not claiming that they're the same as "memory addresses" or pointers. They don't have to be. I'm using the term in a strict analogy to the real world, and that's all. It's a downside of the example, but I don't think it does too much harm.)
I might then also talk about value types, and consider what would have happened if
House
had been a value type - as well as discouraging mutable value types.To know whether or not my answer would still be relevant in a language with mutable strings, we'd need to know more about how string literals behaved. A language which was the same as C# in every way other than the mutability of strings would be an awful language, as you could write:
That clearly wouldn't be desirable, so presumably the behaviour of string literals would have to change. You also talk about possible changes to the meaning of the assignment operator, etc... it's hard to make concrete statements about a hypothetical language without knowing exactly how it behaves.