java中参数传递的方式

今天在写代码的时候遇到了一个参数传递的问题,虽然我知道问题出现在哪里,但是问题的原因似懂非懂,看了很久之前写的一篇博客,在网上搜索了几篇文章

看了下,终于彻底弄懂了这个问题的原因,写篇文章总结下。

首先我们得明白几个概念:按值传递,按引用传递,栈内存,堆内存的区别。

一按值传递:按值传递传递的是数值,传递的时候会在内存中另开辟一块空间来存储这个数值,如:

	public static void main(String[] args){
		double a = 3.0;
		double b = 3.0;
		Test test = new Test();
		test.play(a,b);
		System.out.println("a:"+a);
		System.out.println("b:"+b);
	}
	
	public void play(double a,double b){
		a = 0.0;
		b = 0.0;
	}


transformLon这个函数中的参数就是按值传递的,a,b传递进去后会在内存中另开辟一块内存空间来存储a,b的值,所以函数里面对a,b的更改不会引起函数外面a,b值的改变

a,b打印出来后的结果为: 可以看出a,b的值并未改变。

二按引用传递:按引用传递其实也是可以理解为按值传递,只不过他这个值不是直接的数值,而是存储数值的地址,但是我们操作修改的却是数值,而不是地址

故按值传递时,会改变前面传过来的对象。如:

	public static void main(String[] args){
		String array[] = new String[]{"hello world"};
		Test test = new Test();
		System.out.println("调用play方法前的array[0]:"+array[0]);
		test.play(array);
		System.out.println("调用play方法后的array[0]:"+array[0]);
	}
	
	public void play(String array[]){
		array[0] = "gaga";
	}

我们来看一下打印的结果: 可以看出array[0]的值在调用play方法前后是不一样的,与前面的按值传递效

果相反。

三栈内存和堆内存:

栈内存是用来保存存储基本数据类型的数据和引用变量及对象。java中的基本数据类型的数值都是保存在栈中,程序员不能够直接的设置堆或栈。栈的主要优点为存取

速度快,缺点为存在于栈的数据大小和生存周期是确定的,缺乏灵活性。堆用于存放所有由new关键字所创建对象指向的数值的地址,并不是这个对象的地址。如:

由new 所创建的包装数据类型,Double,String 等 对象的数值则是保存在堆中。在堆中分配的内存由java虚拟机的垃圾回收器(Garbage Collection)GC自动回收。

具体栈和堆的区别可以去看一下我之前写的一篇文章:java中堆和栈的区别

介绍了完了按值传递,按应用传递以及栈内存和堆内存之后,我们从内存方面来分析按值传递和按引用传递的区别。

首先我们看一下按值传递时,代码的内存模型图:

 

我们看一下按值传递时,a的内存模型的变迁,可以看出当 定义 doube a = 3.0;时程序会在栈内存中分配一块空间,将数值3.0保存在这块空间中,当将a 作为参数传递

给play方法时,程序会在内存中另外开辟一块空间A,用来保存a的数值3.0,当在方法play中对参数a进行了修改,a的值并未改变,改变的是A内存中的数值,他由3.0变

成了0.0。A中内存的数值和a中内存的数值没有任何关系。

上面就是按值传递的原理。

接下来我们来了解一下,按引用传递时,代码的内存模型:

我们看下按引用传递时的内存模型,了解引用传递时的内存模型就必须了解栈内存和堆内存,之前已经介绍过了,就不在这里在赘述了。从这个模型我们可以知道

当new 出Array数组时,会在栈内存中分配一区域,array数组有多少个元素就会分配多少块区域 。假设array[0]对象分配的是“地址a”,array[0]的数值则是在堆内存

中开辟了一块区域用于保存,当array[0]作为参数传递到play方法当中时,程序会在栈内存中分配一块区域保存array[0]对象(不是array[0]的数值,堆内存中只能通过

new 关键字来开辟区域)即:地址a,当我们在play方法中修改array[0]对象的数值时,其实是修改堆中保存的数值,而不是array[0]对象。于是堆中的数值由gaga被

改变为hello world,于是当我们打印出array[0]修改前后的数值时,可以看出已经改变了。这就是按引用传递时的原理。

按引用传递,其实也是按值传递,只不过他传递的是数值的地址,而不是数值。我们只要记住,凡是通过new关键字创建出来的对象,进行传递时都是按引用传递

基本数据类型的传递都是按值传递。按应用传递传递的是栈中的地址,按值传递传递的是栈内存中的值,这就是按值传递和按引用传递的主要区别。

 参考资料:

http://www.shaccp.com/azxxx/2012/2005.html

http://blog.sina.com.cn/s/blog_59ca2c2a0100qhjx.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值