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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

class Dem
{
        String temp = "hello";
}
public class Demo
{
        public static void main(String args[])
        {
                Dem d1 = new Dem();
                d1.temp = "world";
                System.out.println("调用之前"+ d1.temp);
                fun(d1);
                System.out.println("调用之后" + d1.temp);
        }
        public static void fun(Dem d2)
       
                d2.temp = "MLDN";
        }
}

那个大神帮忙解释一下,最好能够画个内存示意图,谢谢啦

点评

认真去看视频吧,视频中对对象在内存的分析讲得很详细的  发表于 2014-4-22 13:22

9 个回复

正序浏览
如果是 String s1="abc";在字符串池中如果不存在“abc”则开辟空间存入“abc”并指向s1
如果再 String s2="abc";或者  s1="def";s2会指向原先的字符"abc" s1会重新指向"def"的内存地址!
你这程序字符串变量时作为类对象存在堆栈中的!堆栈中是可以存在重复的对象,并且可以任意修改数据的。
即使d1.temp="hello" d2.temp也 等于"hello" 在堆栈中照样是开辟两个对象存储,只是刚好数据一样罢了!

String a="a";
String b="b";
String c="ab";
String d="ab";
String e=a+b;
程序中用来存放数据的内存分为四块
1、全局区(静态区)(static)
2、文字常量区 :常量字符串就是放在这块区域,即是我们常说起的常量池。
3、栈区(stack):存放函数的参数值,局部变量的值等。
4、堆区(heap) : 存放对象

当我们定义字符串
String a = "a";
a在栈区,“a”是字符串常量,在常量池中
String b = "b";
b在栈区,“b”在常量池
String c="ab";
c在栈区,“ab”在常量池
String d="ab";
d在栈区,这个时候常量池里已经有"ab",所以直接使用已经有的那个“ab”
所以这个时候c和d都指向的常量池里面的同一个“ab”
String e=a+b;
e在栈区,a+b实际上产生了一个新的String对象,既然是String对象,所以结果“ab”放在堆区中,即e指向的是堆里的“ab”
这样的情况下,c==d为true,c==e为false
////////////////////////////////////
另外,如果定义的是字符串对象
String str1 = new String("ab");
str1在栈区,创建的“ab”字符串对象在堆区
String str2 = new String("ab");
str2在栈区,又创建的一个新的“ab”对象也在堆区,不过和刚才的“ab”不是同一个。
相当于堆区中有两个字符串对象,不过正好内容都是“ab”而已。

所以str1==str2为false

常量池里面放着的常量字符串可以重复使用,但是必须是你直接使用的该字符串,像a+
b这种形式虽然得到的结果是“ab”,但并不是使用的字符串常量“ab”

希望对你有所帮助!
回复 使用道具 举报
曹冬明 发表于 2014-4-22 12:32
改变的不是字符串的值,只是重新给d1赋了一个值,之前那个字符串被擦写,被垃圾回收机制给回收了 ...

明白了,谢谢了
回复 使用道具 举报
秦久启 发表于 2014-4-22 12:04
先说声谢谢您,但是我这个java书上面的内存图是这样的,让我很不解这个不是改变了temp的值了吗?

...

改变的不是字符串的值,只是重新给d1赋了一个值,之前那个字符串被擦写,被垃圾回收机制给回收了
回复 使用道具 举报
曹冬明 发表于 2014-4-22 11:45
改变的不是字符串的值,而是成员变量d1的值

先说声谢谢您,但是我这个java书上面的内存图是这样的,让我很不解 这个不是改变了temp的值了吗?

回复 使用道具 举报
二小傻 发表于 2014-4-22 11:41
String temp = "hello";这样定义字符串会首先检查字符串池中是否存在"hello",如果有则直接赋给temp ,如果 ...

首先非常的谢谢您,这个我明白你的意思是,temp是字符串类型,String temp = "hello";这个一旦声明不就不可以改变了,但是为什么之后又变成成了world,MLDN了呢?这就是我不解的地方。
回复 使用道具 举报
因为字符串是在内存的方法区中,不能被改变。
回复 使用道具 举报
改变的不是字符串的值,而是成员变量d1的值 1.rar (10.09 KB, 下载次数: 147)
回复 使用道具 举报
String temp = "hello";这样定义字符串会首先检查字符串池中是否存在"hello",如果有则直接赋给temp ,如果没有则在字符串池中创建一个"hello"然后再赋给temp。
String temp = new String("hello");这样定义就会和正常new在堆栈中存放引用和数据一样。
不知道你标题什么意思,你可以百度一下字符串池看看。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马