java中的按值传递图例讲解


这几天论坛上有人在讨论java中按值传递的问题,说来说去,都不是十分完整和准确。


我想通过图片和例子更加有助于理解这个概念。


 


先看下面的例子:

public class TestSample{ 

 
 
        public static void link(int i){ 

 
 
               i=2; 

 
 
        } 

 
 
        public static void main(String[] args){ 

 
 
                int i = 1; 

 
 
                link(i); 

 
 
                System.out.println(i); 

 
 
        } 

 

  }


在主函数中定义基本整型变量i,并赋予值1。把i做为参数传给方法link,在link中改变i的值为2。


但是在主函数中输出i时,i的值仍然为1。为什么会这样,这就是java的按值传递,别着急接着往下看。


 


在理解按值传递的概念时,是要区分几种情况的,论坛里的各位弟兄在讲的时候没有区分这些情况,造成十分混乱。


 


根据传递的参数,分成基本变量传参和引用变量传参。


 


先来看基本变量传参,也就是上面的例子。看下图:实箭头代表赋的初值,虚箭头代表改变后的值。


 

Java 数据传输 java数据传输图_按值传递


 


大家可以看到,main()和link()中的i是两个不同的变量,他们的相同点就是把值也就是1传了过来。


如果把link()中的i的值变成2,main()中的i的值是不会跟着变的。


再有就是link()中的i是局部变量,他的生命周期仅是在方法link中,运行完link后,这个变量i就失效,会被回收器回收。


 


再来看引用变量传参,这里面还要分成两种情况,一种是给形参赋予一个新的变量,看下面的例子,

public class TestSample{ 

 
         public static void link(Car i){ 

 
                i=new Track(); 

 
         } 

 
         public static void main(String[] args){ 

 
                 Car i = new Car(); 

 
                 link(i); 

 
                 System.out.println(i); 

 
         } 

 

  }


main()方法定义一个car型变量i,传到link()方法中,然后改变了i的值,返回main()后,输出i的值,他仍然是一个car,不会改变。


看下面的图:


 

Java 数据传输 java数据传输图_class_02


 


方法link()中的变量i,一开始是引向car类型的一个实例的,后来使用i=new Track()语句,把i引向了另一个track型的对象实例。这个操作丝毫不会影响到main()方法中的i。


注意:并不只是使用new这个关键字才能使变量改变引用。


string是一个特例,比如,string s="hello";


s=s+" world";


新的s已经改变了他的引用对象,就象s=new String(s+" world");一样。


 


再看另一种情况,形参并不会改变引用对象,而是改变原来引用对象的值。看例子:

public class TestSample{ 

 
         public static void link(Car i){ 

 
                i.addABS(); 

 
         } 

 
         public static void main(String[] args){ 

 
                 Car i = new Car(); 

 
                 link(i); 

 
                 System.out.println(i); 

 
         } 

 

  }


main()方法定义一个car型变量i,传到link()方法中,然后对i进行addABS()方法的操作。返回到main(),再输出i,发现i已经变成了一个加装了ABS的car了。以上几种情况中,只有这种情况才能对实参进行修改。看下面的图:


 

Java 数据传输 java数据传输图_string_03


 


无论是main()还是link()中的i,一直都是指向同一个实例,在link()中对此实例的任何修改,都会影响到实参i的值。


 


希望大家在传参的时候要分清情况,区别对待。