A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© whocases 黑马帝   /  2012-6-28 19:36  /  1947 人查看  /  5 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 whocases 于 2012-6-29 11:51 编辑

先看下代码
class Demo{
        String temp = "hello" ;                // 此处为了方便,属性暂时不封装
};
public class RefDemo{
        public static void main(String args[]){
                Demo d1 = new Demo() ;        // 实例化Demo对象,实例化
                System.out.println("fun()方法调用之后:" + d1.temp) ;
        }
        public static void fun(Demo d2){                // 此处的方法由主方法直接调用
                d2.temp = "itcast";                         // 修改temp值
        }
};
我想问的是  当String作为一个类的成员时  它在堆中具体是怎么回事
比如  上述代码中  d2.temp = "itcast";  修改Sring类对象时  是不是一样先是创建一个匿名对象  再用temp引用它。。。??如果是这样  那么是不是  原来的“hello”就成垃圾了。。。

5 个回复

倒序浏览
这可以参考下经典的面试题,
1.String 和 StringBuffer的区别,
2.String s = “A” + “B”;的过程中产生了几个String对象

这些题目考察的重点其实就是,String是不可再分配的,如果是对一个字符串做出修改,实质上是创建了一个新的字符串。原来的字符串变成了垃圾
这也是为什么在循环操作String的时候,要尽量使用StringBuffer或StringBuilder的原因。

点评

如果是垃圾,为什么"asd" "asd"两次出现,第一次创建,第二次不用创建?呵呵  发表于 2012-6-29 16:40
回复 使用道具 举报
String是一个特殊的包装类数据。可以用String str = new String("abc");的形式来创建;也可以用String str = "abc";的形式来创建。第一种方式 是每new 一人对象 就在堆内存中开辟一块空间来存放new出来的对象,再把对象的地址指向栈内存中的引用变量str,和普通对象创建的过程一样。第二种方式 是先定义一个名为str的对String类的对象引用变量:String str;在栈中查找有没有存放值为“abc”的地址,如果已经有了值为“abc”的地址,则查找对象,并返回对象的地址给str。如果没有,则开辟一个存放字面值为“abc”的地址,接着在堆内存中创建一个新的String类的对象,并将对象的字符串值指向这个地址。d2.temp = "itcast";中给temp赋了新的对象的地址,原来的hello就没有指向它的引用,就成为了垃圾了。
回复 使用道具 举报
本帖最后由 feigecal 于 2012-6-30 21:38 编辑

String是一个特殊的包装类数据。可以用String str = new String("abc");的形式来创建;也可以用String str = "abc";的形式来创建。第一种方式 是每new 一人对象 就在堆内存中开辟一块空间来存放new出来的对象,再把对象的地址指向栈内存中的引用变量str,和普通对象创建的过程一样。第二种方式 是先定义一个名为str的对String类的对象引用变量:String str;在栈中查找有没有存放值为“abc”的地址,如果已经有了值为“abc”的地址,则查找对象,并返回对象的地址给str。如果没有,则开辟一个存放字面值为“abc”的地址,接着在堆内存中创建一个新的String类的对象,并将对象的字符串值指向这个地址。d2.temp = "itcast";中给temp赋了新的对象的地址,原来的hello就没有指向它的引用,但还在内存中存在,。

点评

如果是垃圾,为什么"asd" "asd"两次出现,第一次创建,第二次不用创建?呵呵  发表于 2012-6-29 16:40
回复 使用道具 举报
本帖最后由 游洪波 于 2012-6-28 22:53 编辑

我给你画了一张针对你这个类的内存使用示意图,相信你看完以后就会明白了

应为你现在的Demo是一个对象,而String类型的变量只是对象中的一个属性,所以操作它不会在内存中开辟新的空间,而是在Demo被实例化的时候会开辟一个空间里边有一个String 的属性而已
回复 使用道具 举报
public class Test15 {
        public static void main(String args[]) {
                Demo d1 = new Demo(); // 实例化Demo对象,实例化               
                System.out.println("fun()方法调用之后:" + d2.temp);// 这你标记的是"fun()方法调用之后:"可你并不是输出的调用之后的..
        }
        public static void fun(Demo d2) { // 此处的方法由主方法直接调用
                d2.temp = "itcast"; // 修改temp值
        }
}
class Demo {
        String temp = "hello"; // 此处为了方便,属性暂时不封装
}
想输出调用之后的改成这样:
package com.heima.changjiajie;
public class Test15 {
        public static void main(String args[]) {
                Demo d1 = new Demo(); // 实例化Demo对象,实例化
                Demo d2 = new Demo();
                Test15.fun(d2);
                System.out.println("fun()方法调用之后:" + d2.temp);
        }
        public static void fun(Demo d2) {
                d2.temp = "itcast";
        }
}
class Demo {
        String temp = "hello";
}
那不是修改String类的对象只是改了引用的内容(也就是堆里存的内容),是创建了新的Demo对象...
楼上的已经说了 没有指向它的引用了,也就成为垃圾了...

点评

如果是垃圾,为什么"asd" "asd"两次出现,第一次创建,第二次不用创建?呵呵  发表于 2012-6-29 16:39
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马