为什么 Go 和 Java 的 String 都要设计成 immutable?

2015-02-19 18:19:46 +08:00
 snnn
为什么Go和Java的String都要设计成immutable? 这样做有什么深意吗?
2457 次点击
所在节点    Go 编程语言
26 条回复
invite
2015-02-19 18:29:31 +08:00
不懂。
shawnclovie
2015-02-19 18:47:09 +08:00
因为把字符串设计成如int一样的基础类型,其它的基础类型都是不可变的。
而且,这样的设计可以减少很多程序设计中的意外的发生。
amyangfei
2015-02-19 18:50:01 +08:00
[What is the benefit of string being immutable in Go language](http://www.quora.com/What-is-the-benefit-of-string-being-immutable-in-Go-language)
snnn
2015-02-19 18:51:28 +08:00
@lightpnr 什么意外?
fwrq41251
2015-02-19 18:55:26 +08:00
snnn
2015-02-19 18:59:20 +08:00
@fwrq41251 照这么说,java就是一陀屎啊。如果这么强调对象不可变,干嘛不速速换成clojure才是王道。
shawnclovie
2015-02-19 19:03:48 +08:00
C code:
const char *a = "ABC"; // 不想让它改变的值,比如是一个全局设置之类
void tolower(char *str){
for (int i = 0; i < strlen(str); ++ i){
((char *)str)[i] += 32;
}
}

tolower((char *)a);
// a就变小写了。
xguru
2015-02-19 19:04:41 +08:00
http://stackoverflow.com/questions/9544182/why-are-strings-immutable-in-many-programming-languages

immutable types are a good thing generally:

They work better for concurrency (you don't need to lock something that can't change!)

They reduce errors: mutable objects are vulnerable to being changed when you don't expect it which can introduce all kinds of strange bugs ("action at a distance")

They can be safely shared (i.e. multiple references to the same object) which can reduce memory consumption and improve cache utilisation.

Sharing also makes copying a very cheap O(1) operation when it would be O(n) if you have to take a defensive copy of a mutable object. This is a big deal because copying is an incredibly common operation (e.g. whenever you want to pass parameters around....)
EPr2hh6LADQWqRVH
2015-02-19 19:20:35 +08:00
哦?难道不是因为内存管理的原因?
incompatible
2015-02-19 19:52:23 +08:00
mutable真的算不上什么好设计。需要一个新的值,你就构造一个新的对象就好了啊。何必如此吝惜内存非要复用先前的对象?
参见java中的java.util.Date和java.util.Calendar。用了JodaTime后,真的是感觉被解放了
tairan2006
2015-02-19 21:48:01 +08:00
不可变的好管理啊…除了C/C++,大部分语言的string都是不可变的吧。
coolcfan
2015-02-19 21:50:48 +08:00
不可变对象对线程安全有非常大的好处。
snnn
2015-02-19 21:51:35 +08:00
@coolcfan 那干嘛数组不也做成不可变的?
chingli
2015-02-19 22:09:10 +08:00
http://www.importnew.com/7440.html

安全、性能,以及可用来实现一些特殊作用。

Go中的字符串是utf-8编码,同一个字符串,不同的字符可能分别占用1、2、3字节,方便使用range遍历。
ovear
2015-02-19 22:35:08 +08:00
=.= 刚好窝对Java的机制稍微熟悉点,详细解释下吧

1、同步\安全
2、性能\省资源
3、简单

首先,在Java里面,String是一个对象。
1、对于在对象中传引用的Java,如果String是可变的,那么将会导致Java的String机制完全毁灭。
于是Java就采取了一种简单又暴力的做法,直接把Java的String设定为不可变的,这样既解决了传引用问题,又可以解决同步/安全问题。

2、为什么说会提升性能,节省资源呢?
如果String是可变的,那么如果程序中有许多相同的String呢?那不是会产生很多相同的String,多浪费资源。
于是Java有了String Pool----下面是我研究时候做的一些笔记
----------笔记--------
26. String是常量,其对象一旦创建完毕就无法改变。当使用+拼接字符串时,会生成新的String对象,而不是向原有的String对象追加内容。
27. String Pool(字符串池)
28. String s = “aaa”;(采用字面值方式赋值)
1) 查找String Pool中是否存在“aaa”这个对象,如果不存在,则在String Pool中创建一个“aaa”对象,然后将String Pool中的这个“aaa”对象的地址返回来,赋给引用变量s,这样s会指向String Pool中的这个“aaa”字符串对象
2) 如果存在,则不创建任何对象,直接将String Pool中的这个“aaa”对象地址返回来,赋给s引用。
29. String s = new String(“aaa”);
1) 首先在String Pool中查找有没有“aaa”这个字符串对象,如果有,则不在String Pool中再去创建“aaa”这个对象了,直接在堆中(heap)中创建一个“aaa”字符串对象,然后将堆中的这个“aaa”对象的地址返回来,赋给s引用,导致s指向了堆中创建的这个“aaa”字符串对象。
2) 如果没有,则首先在String Pool中创建一个“aaa“对象,然后再在堆中(heap)创建一个”aaa“对象,然后将堆中的这个”aaa“对象的地址返回来,赋给s引用,导致s指向了堆中所创建的这个”aaa“对象。
--------------
简单粗暴,有什么不好呢?
ovear
2015-02-19 22:36:48 +08:00
@snnn Java的数组就是不可变的哟,数组的属性就是他的长度和类型了。
你不能把一个String[]变成Integer[]吧
里面的内容其实并不属于数组本身的性质
snnn
2015-02-19 22:47:12 +08:00
C++难道就没有StringPool吗? VC早在上个世纪就对常量字符串做了pool。

https://msdn.microsoft.com/en-us/library/s0s0asdt.aspx

而且C++的std::string本身就是支持引用计数的,要想做pool易如反掌。拿libstdc++来说,每当被修改的时候,检查Rep对象是不是来自静态的pool,如果是,Copy一份再修改之。鉴于大部分string都是不需要被modify的,这么做不会有性能损失。
snnn
2015-02-19 22:48:07 +08:00
@ovear
char[] s=new char[24];
s[0]='a';
ovear
2015-02-19 22:54:51 +08:00
@snnn 这是合法的 有问题么?

关于你说的vc提供的是 [编译时] [编译时] 优化,Java是[运行时] [运行时]优化好么?完全都不同的东西
Gets or sets a value indicating whether to enable read-only string pooling for generating smaller compiled code.
需要我翻译一遍么?
generating smaller compiled code.
生成更小的文件

这个指的是在编译的时候
string a = 'abc';
string b = 'abc';
优化后变成
string a = 'abc';
string b = a;
lz真的认真看了么?

对啦,告诉lz个小技巧,把巨硬的en-us换成zh-cn可以看中文噢,有翻译的说。
比如说
https://msdn.microsoft.com/zh-cn/library/s0s0asdt.aspx
hx1997
2015-02-19 23:01:07 +08:00
@ovear MS 的翻译和看英语原文差不多,甚至更差,更不用说那些机器翻译了。。。。。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/171803

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX