Re: [问题] 请教String的问题

楼主: kdok123 (小天)   2014-12-18 20:00:42
非常感谢大家的热心回应,我完全理解了
现在只剩一个小问题想问...
ex1:
String a = "Hello";
a = "kdok123";
这个结果是new了两个String的空间在Heap
ex2:
Interger a = 3;
a = 4;
结果是new了一个Interger的空间在Heap,a指向的值从3改成了4
以上两个例子体现了String的不可变性
请问例子的观念是对的吗?
另外还有一个小疑惑:为什么java要定义String的不可变性呢?
除了不断的增加heap和GC的负担之外我想不到其他好处欸...
作者: Kenqr (function(){})()   2014-12-18 20:26:00
输出2次一样是因为pass by reference,和不可变无关ex2的a会指到另一个不同的位置,用任何class都会这样
作者: ssccg (23)   2014-12-18 20:33:00
你根本没有懂,就说你的结果跟不可变性"完全"没关系String不可变是String不提供任何方法修改它里面char array存的值,要修改一定是产生新的String object刚进method的str2指向的就是完全同一个String并没另外开一个空间,是之后你自己开新的空间放新的String="abc"相当于=new String(new char[] {'a','b','c'})可变性的意义在于如果有个MutableString class你可以用str2.setValue("abc")去改object的内容而不用写成str2 = new MutableString("abc")只要用的是 = new XXX(),不管哪个class都是一样的结果只要你用的是 = 都是不会变的,因为 = 不是改object里的值而是改reference指向的位址只有primitive type的时候用 = 才是改值
楼主: kdok123 (小天)   2014-12-18 20:53:00
String="abc"的意思是若"String pool没有"abc",则创造一个新空间存放abc,否则指向abcString ob = new String("abc")的意思是"不管String pool里有没有abc,都创造一个空间存放abc因为immutable的特性,才会造成上面的结果,否则任何的赋值动作都会覆蓋原本的值http://www.cnblogs.com/fguozhu/articles/2661055.html
作者: ssccg (23)   2014-12-18 20:57:00
覆蓋原本的值也是覆蓋reference,而不是覆蓋value
楼主: kdok123 (小天)   2014-12-18 20:57:00
参考连结的观念的
楼主: kdok123 (小天)   2014-12-18 21:02:00
这边我认为是immutable的关系,若今天是mutable就改得到或许等我试试上面连结的atomic wrapper class?android studio没有把那个class import进来不能测试...
作者: ssccg (23)   2014-12-18 21:05:00
我是不知道你打算怎么试,但是除了primitive的autowrapper还有String literal("...")以外,其他type都很清楚就是换了物件啊...如果你有学过C++,java的reference type基本上就是pointer如果是C++的pass by reference(&),即使物件是mutable还是可直接改caller func中那个reference的值(指向的位址)或是你可以去用C#试,C#的reference type跟java一样String也是Immutable,但是方法可以pass by reference你的ex1用C# pass by ref版 http://ideone.com/Miptpm
楼主: kdok123 (小天)   2014-12-18 21:43:00
Hi,因为java这边是auto-boxing的,所以以c++的观念来说pointer是指向同一个地方,要修改值的但因为immutable的特性,才没有修改成功我只是想说,如果你认为java的reference就是c++的pointer那在auto-boxing的结果下,你应该会觉得值要被修改才对
作者: ssccg (23)   2014-12-18 23:20:00
immutable不是不能修改reference值,是不能修改object里面的data,你还是直接看上面的C#的范例...既然会C++也给你一个C++版 http://ideone.com/DSzyGI不是我觉得,是java的reference变量真的就是pointer改是改pointer指的位址,但是在call by value的时候改不动caller func里面的pointer变量很明显就call by value/call by reference的差别啊..btw auto-boxing是指对只吃Object子class的地方(如list)自动包wrapper,unboxing是在assign给primitive变量的时候自动改为取值(.xxxValue)而不是assign reference如果全程都是直接用Integer这个class,那与一般class没差别把Integer assign给Integer变量是不会有auto-box/unbox行为
作者: bleed1979 (十三)   2014-12-19 07:28:00
看完这整个讨论串,好难过,想去renew Java 7的认证。
楼主: kdok123 (小天)   2014-12-19 09:22:00
我很想讲得更清楚一点,但前面darkk6大已经画得很清楚了这边的重点应该是immutable/mutable的差别才对如果这边是mutable的class,你说的caller func的pointer变量就会被改到因为我认为这边的观念很重要,才会一直强调,或许其他版友可以加入一起讨论,来厘清这个问题?
作者: ssccg (23)   2014-12-19 09:41:00
就算是mutable class,caller func的pointer还是不会改到因为是pass by value,在传入时只是复制pointer的值d大的图我只能说 // 因为字串的 Immutable... 这句完全错误不管是什么class,用assign (=)的方式,改的永远都是str2指向的位址(pointer value)而已,原本的那个object不会被动到要动原本的object就要用它的method/fieldimmutable意义在于原本的object没有公开的改值method/field用pointer来说的话就是要改object的值一定要先dereference用=只会改pointer存的位址你好像幻想lhs如果是个mutable reference type变量用=会自动把lhs指向的物件中代表value的field拿出来,然后把rhs expression物件中代表value的field里存的值放进去从你上面提auto-boxing可以看出来,可是实际上没这回事=只会把lhs reference直接改成指向rhs的结果物件lhs原本指向什么完全没差,在=的动作中那个物件根本没出场=只有在lhs是primitive type的时候才是赋值(因为primitive)type才有所谓value,如果lhs是reference type,他指向的物件不一定有所谓的value,这时做的都只是改指向的物件

Links booklink

Contact Us: admin [ a t ] ucptt.com