黑马程序员技术交流社区

标题: 看到一个博客里有关string类创建对象个数的问题,求指教 [打印本页]

作者: 魏亮    时间: 2012-9-16 15:20
标题: 看到一个博客里有关string类创建对象个数的问题,求指教
本帖最后由 魏亮 于 2012-9-16 21:05 编辑

语句后面对应的是对象个数,不太懂,请牛人指出内存中的情况

Java String 常量池问题的几个例子 - xbkaishui的专栏 - 博客频道 - CSDN.NET.png.png (9.41 KB, 下载次数: 87)

Java String 常量池问题的几个例子 - xbkaishui的专栏 - 博客频道 - CSDN.NET.png.png

作者: 马睿    时间: 2012-9-16 15:32
本帖最后由 马睿 于 2012-9-16 15:36 编辑

装箱拆箱问题

当你定义String s3 = "abc"的时候,实际上这里进行了一个装箱操作String s3 = new String("abc"),注意String是Object的子类,而不是基本数据类型

于是在内存里开辟了3个字节byte空间,也就是说对于s3其内部成员变量byte[] b的长度为3



当你进行String s6 = s3 + "d"先进行了拆箱操作,将s3拆箱,然后,然后把d加入拆箱后的s3的字符数组,合并之后,再装箱到s3中,注意是s3,由于加了一个"d"超过了原始长度3,因此,系统会再为String s3开辟一个相等大小的控件(类似c语言的malloc函数开辟空间,一般链表也是开辟相等长度空间)
所以一开辟也就开辟了额外3个,总共6个字节的空间



对于其下方范例,s7实际运行过程是这样的,字符串实际相加做+操作时候,实际上不是真的直接加了,都需要通过中介容器String的
所以String s7 = "abc" + "d"实际的操作是这样的
String s7 = new String("abc") + new String("d")   (然后会拆箱成字节数组操作,拆完合并后,会装箱给new String("abc")  这个容器里)
一个大小为3,一个大小为1,计算机编译运算自右向左,所以会将String("abc")的3格扩充为,因为默认长度是3,一扩充就扩充6格

最后再赋给s7 ,s7也就得到长度为6了
作者: 武庆东    时间: 2012-9-16 15:37
关于新建对象问题总结:
String str = new String("abc");
String str = "abc";
两种的形式来创建,第一种是用new()来新建对象的,它会在存放于堆中。每调用一次就会创建一个新的对象。
而第二种是先在栈中创建一个对String类的对象引用变量str,然后查找栈中有没有存放"abc",如果没有,则将"abc"存放进栈,并令str指向”abc”,如果已经有”abc” 则直接令str指向“abc”。

比较类里面的数值是否相等时,用equals()方法;当测试两个包装类的引用是否指向同一个对象时,用==,下面用例子说明上面的理论。
String str1 = "abc";
String str2 = "abc";
System.out.println(str1==str2); //true
可以看出str1和str2是指向同一个对象的。

String str1 =new String ("abc");
String str2 =new String ("abc");
System.out.println(str1==str2); // false
用new的方式是生成不同的对象。每一次生成一个。
作者: 广驰    时间: 2012-9-16 15:37
String s1 = new String("abc"),在java里面一个字符串就是一个常量对象,而且不可以更改的,所以“abc”为一个对象,而String(String s)初始化一个新创建的 String 对象,表示一个与该参数相同的字符序列;换句话说,新创建的字符串是该参数字符串的一个副本。
这样String s1 = new String("abc");String s2 = new String("abc")就有了两个“abc”的副本和一个“abc”

String s3 = “abc”;String s4 = “abc”就是把“abc”的地址赋值s3,s4,并没有创建新对象,而是创建了“abc”的引用,java中的引用的概率很重要,一定要分清楚

String s5 = “abcd”;这句话就不用解释了吧

String s6 = s3+“d”;前面说过,一个字符串就是一个对象,所以d是一个对象,而字符串相加后赋值给了s6,这又是一个新对象,虽然s6也是“abcd”,看起来和s5一样,但是并不相等,只是用equlas方法判断他们内容相同,因为s3是可变的

至于最后一个在常量池中都有,所以并没有创建新的对象,而是创建了引用s7指向“abcd”



作者: 马睿    时间: 2012-9-16 15:46
为了证明,“abc”字符串就是String的装箱

我给出一个例子

其实很简单的例子
"abc".toString()


虽然很简单,不过你仔细思考才能发现,为什么"abc"能调用方法??
嘿嘿显而易见,因为本身被装箱成String类型所以认得出


至于变成6字节问题,上面我已经讲的很清楚了,这个就是Integer类型你非要给它赋个128一样,会额外开辟一个等长空间,在视频中有对Integer的装箱操作讲解
作者: 魏亮    时间: 2012-9-17 07:38
应广驰 发表于 2012-9-16 15:37
String s1 = new String("abc"),在java里面一个字符串就是一个常量对象,而且不可以更改的,所以“abc”为 ...

解释的很清楚,谢了




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2