黑马程序员技术交流社区

标题: String s = new String(“xyz”)创建的对象的内存分配 [打印本页]

作者: 胡建彪    时间: 2012-10-10 21:55
标题: String s = new String(“xyz”)创建的对象的内存分配
String s = new String(“xyz”);创建了几个String Object?        产生了两个实例化对象,一个是匿名对象”xyz”,另一个是通过关键字new实例化的。
那么这两个对象对应在内存中的哪一片空间中呢?初步猜测  ”xyz” 和 new 实例化的全部在堆内存中,s 在栈内存中,但是“xyz” 对应的引用在哪里呢?



作者: 燃烧端午    时间: 2012-10-10 22:02
一个是编译时决定的,最后放在常量池中。一个是运行时放在堆里面的。
常量池中只可能只有一个“xyz”,但是堆中可能有多个;
如果是String s= "xyz"这样的,s这个引用就会直接指向常量池的"xyz",而不会是指向你在堆中创建的“xyz”。
作者: 胡建彪    时间: 2012-10-10 22:17
燃烧端午 发表于 2012-10-10 22:02
一个是编译时决定的,最后放在常量池中。一个是运行时放在堆里面的。
常量池中只可能只有一个“xyz”,但是 ...

你说的常量池是方法区么? 即Static修饰的成员 在内存中的位置。
作者: zczcyc0201    时间: 2012-10-11 10:19
创建String有两种方法
String s1="你好";
String s2=new String("你好");
这两种方法的差异在于第一种方法在对象池中拿对象,第二种方法直接生成新的对象。Java虚拟机在启动的时候会实例化9个对象池,这9个对象池分别用来存储8种基本类型的包装类对象和String对象。当我们在程序中直接用双引号括起来一个字符串时,JVM就到String的对象池里面去找看是否有一个值相同的对象,如果有,就拿现成的对象指向当前引用,如果没有就在对象池里面创建一个对象,并返回。所以我们发现下面的代码输出true:
String s1="你好";
String s2="你好";
System.out.println(str1==str2); //结果为true
这说明str1和str2指向同一个对象,因为它们都是在对象池中拿到的,而下面的代码输出为false:
String s3="你好"
String s4=new String("你好");
System.out.println(str3==str4); //结果为false

因为在任何情况下,只要你去new一个String对象那都是创建了新的对象。
与此类似的,在JDK5.0里面8种基本类型的包装类也有这样的差异:
Integer i1=5;//在对象池中拿
Integer i2 =5;//所以i1==i2
Integer i3=new Integer(5);//重新创建新对象,所以i2!=i3
对象池的存在是为了避免频繁的创建和销毁对象而影响系统性能
作者: 唐永康    时间: 2012-10-11 13:24
我自己画了一个图,对象是存在于堆里面的。
作者: cehkongfu    时间: 2012-10-11 22:31
String str = new String("abc");

第一个对象是“abc”,每一个字符串都是一个常量,不可改变的,放在常量池里面,
而string new 出来的对象又是一个对象,他有一个实实在在的内存空间存放“abc”在常量池中的地址,而str是指向这块空间的引用,而通过这种方式的string对象中指向"abc"的值可以被改变,可以指向“bcd”,“dfefr”等等,但是str的地址不会变

这里要明白,字符串常量不完全等于字符串对象,其实上面的一条语句用了三个内存空间,“abc"的,new出来的String存放的,还有一个是Str的。而通过例如String str = “abc”创建的实例,就只有两个空间。

这么说不知道你能不能明白
作者: 胡建彪    时间: 2012-10-12 07:39
cehkongfu 发表于 2012-10-11 22:31
String str = new String("abc");

第一个对象是“abc”,每一个字符串都是一个常量,不可改变的,放在常量 ...

Thanks for replying .
作者: 陈虹旭    时间: 2012-10-12 12:03
学习了 嘿嘿...




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