关闭

java中按值传递与引用传递

228人阅读 评论(0) 收藏 举报
分类:
  

        前天在做系统的时候被Java中参数传递问题卡了一下,回头查阅了相关的资料,对参数传递问题有了新的了解和掌握,但是有个问题感觉还是很模糊,就是Java中到底是否只存在值传递,因为在查阅资料时,经常看到有人说Java只有值传递,但有人说既有值传递,也有引用传递,对于两个观点个人觉得应该是站的角度不同而得出两个不同的说法,其实两个说法其中的原理是一样的,只要咱们懂得其中的原理,那么至于叫什么也就无所谓了,下面是我在网上看到的一个帖子,解释的感觉挺全面,就转过来,以供以后学习参考:

       

1:按值传递是什么

指的是在方法调用时,传递的参数是按值的拷贝传递。示例如下:

  1. public class TempTest {  
  2. private void test1(int a){  
  3. //做点事情  
  4. }  
  5. public static void main(String[] args) {  
  6. TempTest t = new TempTest();  
  7. int a = 3;  
  8. t.test1(a);//这里传递的参数a就是按值传递  
  9. }  
  10. }  

按值传递重要特点:传递的是值的拷贝,也就是说传递后就互不相关了。

示例如下:

  1. public class TempTest {  
  2. private void test1(int a){  
  3. a = 5;  
  4. System.out.println("test1方法中的a="+a);  
  5. }  
  6. public static void main(String[] args) {  
  7. TempTest t = new TempTest();  
  8. int a = 3;  
  9. t.test1(a);//传递后,test1方法对变量值的改变不影响这里的a  
  10. System.out.println(”main方法中的a=”+a);  
  11. }  
  12. }  

运行结果是:

  1. test1方法中的a=5  
  2. main方法中的a=3  


2:按引用传递是什么

指的是在方法调用时,传递的参数是按引用进行传递,其实传递的引用的地址,也就是变量所对应的内存空间的地址。

示例如下:

  1. public class TempTest {  
  2. private void test1(A a){  
  3. }  
  4. public static void main(String[] args) {  
  5. TempTest t = new TempTest();  
  6. A a = new A();  
  7. t.test1(a); //这里传递的参数a就是按引用传递  
  8. }  
  9. }  
  10. class A{  
  11. public int age = 0;  
  12. }  

3:按引用传递的重要特点

传递的是值的引用,也就是说传递前和传递后都指向同一个引用(也就是同一个内存空间)。

示例如下:


  1. public class TempTest {  
  2. private void test1(A a){  
  3. a.age = 20;  
  4. System.out.println("test1方法中的age="+a.age);  
  5. }  
  6. public static void main(String[] args) {  
  7. TempTest t = new TempTest();  
  8. A a = new A();  
  9. a.age = 10;  
  10. t.test1(a);  
  11. System.out.println(”main方法中的age=”+a.age);  
  12. }  
  13. }  
  14. class A{  
  15. public int age = 0;  
  16. }  

运行结果如下:

  1. test1方法中的age=20  
  2. main方法中的age=20  

4:理解按引用传递的过程——内存分配示意图

要想正确理解按引用传递的过程,就必须学会理解内存分配的过程,内存分配示意图可以辅助我们去理解这个过程。

用上面的例子来进行分析:

(1):运行开始,运行第8行,创建了一个A的实例,内存分配示意如下:



(2):运行第9行,是修改A实例里面的age的值,运行后内存分配示意如下:


(3):运行第10行,是把main方法中的变量a所引用的内存空间地址,按引用传递给test1方法中的a变量。请注意:这两个a变量是完全不同的,不要被名称相同所蒙蔽。

内存分配示意如下:


由于是按引用传递,也就是传递的是内存空间的地址,所以传递完成后形成的新的内存示意图如下:


也就是说:是两个变量都指向同一个空间。

(4):运行第3行,为test1方法中的变量a指向的A实例的age进行赋值,完成后形成的新的内存示意图如下:


此时A实例的age值的变化是由test1方法引起的

(5):运行第4行,根据此时的内存示意图,输出test1方法中的age=20

(6):运行第11行,根据此时的内存示意图,输出main方法中的age=20


5:对上述例子的改变

理解了上面的例子,可能有人会问,那么能不能让按照引用传递的值,相互不影响呢?就是test1方法里面的修改不影响到main方法里面呢?

方法是在test1方法里面新new一个实例就可以了。改变成下面的例子,其中第3行为新加的:

  1.  public class TempTest {  
  2.  private void test1(A a){  
  3.  a = new A();//新加的一行  
  4.  a.age = 20;  
  5.  System.out.println("test1方法中的age="+a.age);  
  6.  }  
  7.  public static void main(String[] args) {  
  8.  TempTest t = new TempTest();  
  9.  A a = new A();  
  10.  a.age = 10;  
  11.  t.test1(a);  
  12.  System.out.println(”main方法中的age=”+a.age);  
  13.  }  
  14. }  
  15. class A{  
  16.  public int age = 0;  
  17. }  

运行结果为:

  1. test1方法中的age=20  
  2. main方法中的age=10  

为什么这次的运行结果和前面的例子不一样呢,还是使用内存示意图来理解一下

6:再次理解按引用传递

(1):运行开始,运行第9行,创建了一个A的实例,内存分配示意如下:

(2):运行第10行,是修改A实例里面的age的值,运行后内存分配示意如下:

(3):运行第11行,是把main方法中的变量a所引用的内存空间地址,按引用传递给test1方法中的a变量。请注意:这两个a变量是完全不同的,不要被名称相同所蒙蔽。

内存分配示意如下:

由于是按引用传递,也就是传递的是内存空间的地址,所以传递完成后形成的新的内存示意图如下:


也就是说:是两个变量都指向同一个空间。

(4):运行第3行,为test1方法中的变量a重新生成了新的A实例的,完成后形成的新的内存示意图如下:

(5):运行第4行,为test1方法中的变量a指向的新的A实例的age进行赋值,完成后形成的新的内存示意图如下:

注意:这个时候test1方法中的变量a的age被改变,而main方法中的是没有改变的。

(6):运行第5行,根据此时的内存示意图,输出test1方法中的age=20

(7):运行第12行,根据此时的内存示意图,输出main方法中的age=10

7:说明

(1):“在Java里面参数传递都是按值传递”这句话的意思是:按值传递是传递的值的拷贝,按引用传递其实传递的是引用的地址值,所以统称按值传递。

(2):在Java里面只有基本类型和按照下面这种定义方式的String是按值传递,其它的都是按引用传递。就是直接使用双引号定义字符串方式:String str = “Java私塾”;

0
0
查看评论

JS是按值传递还是按引用传递?

数据类型 在 javascript 中数据类型可以分为两类: 原始数据类型值 primitive type,比如Undefined,Null,Boolean,Number,String。引用类型值,也就是对象类型 Object type,比如Object,Array,Function,D...
  • lzm18064126848
  • lzm18064126848
  • 2016-12-11 23:05
  • 1145

java中的按值传递和按引用传递

先使用int实验: public class TTEST { private static List mList = new LinkedList(); public static void main(String[] args) { int a = 0; changeA(a);...
  • howlaa
  • howlaa
  • 2014-07-15 16:49
  • 1754

java中按值传递和引用传递区别

java中传参方式
  • morgerton
  • morgerton
  • 2017-02-08 12:54
  • 1351

JS是按值传递还是按引用传递

按值传递 VS. 按引用传递 按值传递(call by value)是最常用的求值策略:函数的形参是被调用时所传实参的副本。修改形参的值并不会影响实参。   按引用传递(call by reference)时,函数的形参接收实参的隐式引用,而不再是副本。这意味着函数形参的值如...
  • a1104381972
  • a1104381972
  • 2015-08-31 10:43
  • 990

java中按值传递还是按引用传递--string

thinking in Java 中解释是这样的:不管是基本类型还是对象类型,都是传值。这种说法是把引用的副本也看作了一种“值”,也能够说的过去,但是本人还是更赞成将按值传递和按引用传递分开比较好理解。引自----http://smile2015.blog.51cto.com/9250194/162...
  • wabiaozia
  • wabiaozia
  • 2016-09-10 08:19
  • 1142

c语言 按值传递机制和按引用传递机制

在调用自定义函数时经常会遇到给被调用函数传递参数。注意参数和变元的区别,eg:声明一个函数如下:int fun(int a,int *pnumber),其中的a和pnumber就是参数。 int main(void) { int b,c; b= fun(int c,int *p...
  • ICE_CHB
  • ICE_CHB
  • 2016-07-01 22:50
  • 1880

Python中值传递和引用传递区别

python中对一个函数可以传递参数,但是如何分辨是值传递还是引用传递,不是程序员手动控制的,而是python根据你传入的数据对象,自动识别的。 如果你传入的参数对象是可变对象:列表,字典,这个时候就是引用传递,如果参数在函数体内被修改,那么源对象也会被修改。 如果你传入的参数对象是不可变的对象...
  • xuqiaobo
  • xuqiaobo
  • 2017-05-16 10:59
  • 999

python中是按值传递参数还是按引用传递参数

在学习python函数的时候,遇到了一个非常有趣的问题: 在函数中的参数是如何传递的:是传值?还是传引用?当然,结果我们是知道的,肯定是传引用的。 现在,我们来测一下我们的结论: ===== 修改list,Code: # 添加了一个string类型的元素添加到末尾 def ChangeList(...
  • u011394362
  • u011394362
  • 2015-07-09 13:30
  • 3254

按值传递还是按引用传递详细解说

1:按值传递是什么 指的是在方法调用时,传递的参数是按值的拷贝传递。示例如下: [java] view plain copy     public class TempTest {       private void te...
  • xx123698
  • xx123698
  • 2016-12-12 15:14
  • 919

JS 中没有按地址(引用)传递,只有按值传递

很多人,包括我,受书本知识消化不彻底的影响,认为 JS 中参数有两种传递方式:数字、字符串等按值传递;数组、对象等按地址(引用)传递。对此种观点,我们要谨慎。 var v1 = [] var v2 = {}; var v3 = {}; function...
  • www3300300
  • www3300300
  • 2014-09-01 11:08
  • 1214
    个人资料
    • 访问:60950次
    • 积分:1060
    • 等级:
    • 排名:千里之外
    • 原创:36篇
    • 转载:59篇
    • 译文:0篇
    • 评论:14条
    文章分类
    最新评论
    算法学习
    记录算法