黑马程序员技术交流社区

标题: 在内存中赋值的问题 [打印本页]

作者: whocases    时间: 2012-6-28 19:36
标题: 在内存中赋值的问题
本帖最后由 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”就成垃圾了。。。

作者: 赵倩倩    时间: 2012-6-28 19:43
这可以参考下经典的面试题,
1.String 和 StringBuffer的区别,
2.String s = “A” + “B”;的过程中产生了几个String对象

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

作者: 孙飞    时间: 2012-6-28 22:08
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就没有指向它的引用,就成为了垃圾了。
作者: 孙飞    时间: 2012-6-28 22:09
本帖最后由 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就没有指向它的引用,但还在内存中存在,。
作者: 游洪波    时间: 2012-6-28 22:51
本帖最后由 游洪波 于 2012-6-28 22:53 编辑

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

应为你现在的Demo是一个对象,而String类型的变量只是对象中的一个属性,所以操作它不会在内存中开辟新的空间,而是在Demo被实例化的时候会开辟一个空间里边有一个String 的属性而已
作者: 常佳杰    时间: 2012-6-28 23:34
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对象...
楼上的已经说了 没有指向它的引用了,也就成为垃圾了...





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