String 变量只要被赋值就等于新new一个String对象
来源:互联网 发布:网络在线测速 编辑:程序博客网 时间:2024/05/20 11:36
引言
字符串只要赋值就相当于新new一个对象,字符串变量指向这个新new的对象,之前的对象就成了没有引用指向的对象了。
看下面代码:
public class Example { String str = new String("good"); char[] ch = { 'a', 'b', 'c' }; public static void main(String args[]) { Example ex = new Example(); ex.change(ex.str, ex.ch); System.out.print(ex.str + " and "); System.out.print(ex.ch); } public void change(String str, char ch[]) { str = "test ok"; ch[0] = 'g'; }}
结果输出是什么?
我以为会是good and abc,因为形参无法改变实参的值嘛(值传递的时候应该是这样的),但是正确结果是good and gbc,后来明白,引用传递给形参(查了一些资料,有的说java当中只有值传递,没有引用传递;有的又说两种传递都有,我也弄不太清楚),然后在形参里面做改变的时候,实参也是会改变的,类比C语言的指针。原来如此,所以ch[0]的值会改变,可为什么字符串str的值又不变呢?我觉得有必要检查一下对象的hash码。
看下面的代码:
public class Example { String str = new String("good"); char[] ch = { 'a', 'b', 'c' }; public static void main(String args[]) { Example ex = new Example(); ex.change(ex.str, ex.ch); System.out.println("ex str hash"+ex.str.hashCode());//获得ex.str的hashcodeSystem.out.println("ex ch hash"+ex.ch.hashCode());//获得ex.ch的hashcode System.out.print(ex.str + " and "); System.out.print(ex.ch); } public void change(String str, char ch[]) { str = "test ok";System.out.println("change str hash"+str.hashCode());//获得change 方法中str的hashcode ch[0] = 'g'; System.out.println("ch hash"+ch.hashCode());//获得change 方法中ch的hashcode }}
就加了4行打印hash码,hash码输出如下:
看到结果,发现在change方法中的数组和在main中的数组是同样的hashcode,说明修改的是同一个对象(该对象的实体在堆heap上),所以在change方法中修改了数组以后,main当中的ex.ch肯定也会被修改,因为是在堆上的同一个对象。
但是,在change方法中的str和main当中的ex.str的hashcode居然是不一样的!!这说明在方法change中的形参str指向的并不是main当中的ex.str指向的对象,所以在change中做修改,当然不会影响main中的ex.str的对象的内容。
那么问题来了,既然都是引用传递给形参,为什么数组的就是指向堆上的同一个对象,而字符串就不是指向同一个堆上的对象呢?
上面的代码稍作修改,如下:
public class Example { String str = new String("good"); char[] ch = { 'a', 'b', 'c' }; public static void main(String args[]) { Example ex = new Example(); ex.change(ex.str, ex.ch); System.out.println("ex str hash"+ex.str.hashCode());//获得ex.str的hashcodeSystem.out.println("ex ch hash"+ex.ch.hashCode());//获得ex.ch的hashcode System.out.print(ex.str + " and "); System.out.print(ex.ch); } public void change(String str, char ch[]) { System.out.println("change str hash"+str.hashCode());//获得change 方法中str的hashcode //<span style="color:#ff0000;">在str重新赋值之前就打印change方法中的形参str的对象的hashcode</span> str = "test ok"; ch[0] = 'g'; System.out.println("ch hash"+ch.hashCode());//获得change 方法中ch的hashcode }}
这时hashcode一样了。
换句话说,在传递参数的时候,确实是引用传递过来,但是当重新给字符串赋值的时候,新赋值的字符串变量(引用)就不再指向原来的堆上的对象!
看下面代码:
String s = "hello";System.out.println(s.hashCode());s = "world";System.out.println(s.hashCode());
输出结果:
只要一赋值,对象的hashcode就改变,也就是说只要一赋值,就新生成一个对象,而不是在原对象上做更改。
执行完这几行代码以后,在堆上面有两个对象!!一个是“hello”,一个是“world”。也就是说,在改变字符串的内容时,它没有在原来的堆内存上重写内容,而是新划出一块堆内存保存新赋的字符串内容!这个机制像什么?对,就是新new一个对象,所以我认为下面第2行和第3行代码是等价的:
String s = "hello";s = "world";s = new String("world");s先指向new出的“hello”对象,当对s重新赋值的时候(执行第2行代码),s这个引用变量会指向新的一块堆内存所保存的对象“world”,而之前的”hello“对象会成为没有引用指向的对象,我认为不久就会被GC。
至此,得出一个结论:字符串只要赋值就相当于新new一个对象,字符串变量指向这个新new的对象,之前的对象就成了没有引用指向的对象了。
- String 变量只要被赋值就等于新new一个String对象
- java 中用,String new 一个新对象
- String直接赋值和new一个对象的理解
- 在java中用String new一个新对象时
- 用 new 关键字对一个String 变量赋值和直接赋值有什么不同
- 用 new 关键字对一个String 变量赋值和直接赋值有什么不同
- 用 new 关键字对一个String 变量赋值直接赋值有什么不同
- 反射:new 一个String对象
- 用 new 关键字对一个String 变量赋值和用literal值直接赋值有什么不同
- 用 new 关键字对一个String 变量赋值和用literal值直接赋值有什么不同
- 用 new 关键字对一个String 变量赋值和用literal值直接赋值有什么不同
- 用new关键字对一个String 变量赋值和用literal值直接赋值有什么不同(转)
- 用new关键字对一个String 变量赋值和用literal值直接赋值有什么不同(转)
- java String赋值问题,nul,new String()函数赋值问题
- JAVA中String直接赋值与new出来的对象赋值的区别
- String的特点一旦被赋值就不能改变图解
- java中string对象赋值
- new String() 和直接赋值的注意事项
- 最简单的基于FFmpeg的移动端例子:Android 视频解码器-单个库版
- FastDFS配置文件操作说明
- OWASP安全编码规范快速参考的术语
- Swift---一门智能型的编程语言
- UVALive 6680Join the Conversation
- String 变量只要被赋值就等于新new一个String对象
- C++溢出对象虚函数表指针
- ArrayList的默认初始容量及扩容
- LightOJ 1085
- JavaScript事件代理和委托(Delegation)
- 让sql语句不排序,按照in语句的顺序返回结果
- 51nod 1268 和为k的组合
- [LeetCode]344. Reverse String
- POJ 2749 || HDU 1815 Building roads 2-sat