JAVA值传递和引用传递与栈,堆和常量池

http://www.cnblogs.com/gw811/archive/2012/10/18/2730117.html

先学习了解上面的关于JAVA内存管理的各个内存区域的功能:

关于JAVA值传递和引用传递首先得了解栈和堆以及常量池的基本概念:

举个栗子:

String  s = ‘"lizhi";

直接初始化一个String类型的变量的内部实现步骤:①JVM首先在栈中初始化一个String类型的引用 ②然后去常量池中寻找是否存在lizhi这个字符串③如果存在,则将栈中的引用直接指向常量池的lizhi,如果不存在,则在常量池新建一个lizhi,并用栈中的引用指向这个lizhi。

String t = new String("newlizhi");

使用new初始化一个String类型的变量的内部实现步骤:①JVM首先在栈中初始化一个String类型的引用②然后在堆中开辟一块新的内存空间,并将lizhi放进去③将栈中的引用指向堆中的内存地址

public class C1215_1 {
	public static void main(String[] args) {
		String a = "lizhi";
		String a1 = "lizhi";
		String b = new String("lizhi"); 
		StringBuffer c = new StringBuffer("lizhi");
		System.out.println(a == a1);
		System.out.println(a == b);
		change(a,b,c);
		System.out.println("a :"+a+"\n"+"b :"+b+"\n"+"c :"+c);
	}
	public static void change(String a,String b,StringBuffer c){
		a = "change";
		b = "change";
		c.append("change");
	}
}
结果是:

true
false
a :lizhi
b :lizhi
c :lizhichange
由上面的代码就可以看得出来;a和a1都是指向常量池中的同一块内存 地址,所以相等。

然后对于值传递和引用传递,我的理解是:所谓的值传递和引用传递,传递的都只是这个数据的栈中的引用的副本;

就还是以上面的栗子来说:当传入的参数是a时,实际上是传入了一个a指向(指向常量池中"lizhi")的副本。a(副本) = "change"这句话的实现步骤跟上面的初始化a是一样的:①在常量池中寻找是否存在change这个字符串,如果存在,则直接指向它;如果不存在,则新建change然后指向它;这时候,无论存不存在这个change,原来常量池之中的lizhi都是依然存在的,且a依旧是指向lizhi的;

当传入的参数是b时,基本步骤跟上面一样,但是有一点不同的是,b指向原来是指向堆的,但是b的副本却是指向常量池的。

当传入的参数是c是,传入的c的副本跟c都是指向栈中的lizhi的内存地址的;当对其进行c.append"change"')操作时,则是直接对其栈中的lizhi的内存进行操作,改变的是lizhi内存地址之中的数据;且因为c也是指向这块内存,所以方法执行完毕,c指向的内存地址的数据发生了变化;

由此得出:所谓的值传递跟引用传递归根结底的区别在于,

每当对指向常量池的数据进行改变的时候,是先去寻找你所要变化的值,如果存在,直接指向;如果不存在,新建一个,直接指向。这样操作的结果是:原来的值依旧存在于常量池之中(常量池中的数据是共享的)

但是对于栈中的数据,则是直接在对应的内存地址中进行数据改变,这样会使得原数据发生变化。JAVA值传递和引用传递与栈,堆和常量池_第1张图片

你可能感兴趣的:(JAVA)