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放进去③将栈中的引用指向堆中的内存地址

[java]  view plain  copy
 print ?
  1. public class C1215_1 {  
  2.     public static void main(String[] args) {  
  3.         String a = "lizhi";  
  4.         String a1 = "lizhi";  
  5.         String b = new String("lizhi");   
  6.         StringBuffer c = new StringBuffer("lizhi");  
  7.         System.out.println(a == a1);  
  8.         System.out.println(a == b);  
  9.         change(a,b,c);  
  10.         System.out.println("a :"+a+"\n"+"b :"+b+"\n"+"c :"+c);  
  11.     }  
  12.     public static void change(String a,String b,StringBuffer c){  
  13.         a = "change";  
  14.         b = "change";  
  15.         c.append("change");  
  16.     }  
  17. }  
结果是:

[html]  view plain  copy
 print ?
  1. true  
  2. false  
  3. a :lizhi  
  4. b :lizhi  
  5. 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函数参数传递理解)