java add 参数_java中的参数传递方式

为方便查看,这里引用易水寒的文章,链接地址为http://blog.sina.com.cn/s/blog_59ca2c2a0100qhjx.html

这里的内存模型涉及到两种类型的内存:栈内存(stack)和堆内存(heap)。基本类型作为参数传递时,传递的是这个值的拷贝。无论你怎么改变这个拷贝,原值是不会改变的。看下边的一段代码,然后结合内存模型来说明问题:

public class ParameterTransfer {

public static void main(String[] args) {

int num = 30;

System.out.println("调用add方法前num=" + num);

add(num);

System.out.println("调用add方法后num=" + num);

}

public static void add(int param) {

param = 100;

}

}

这段代码运行的结果如下:

调用add方法前num=30

调用add方法后num=30

程序运行的结果也说明这一点,无论你在add()方法中怎么改变参数param的值,原值num都不会改变。

下边通过内存模型来分析一下。

当执行了int num = 30;这句代码后,程序在栈内存中开辟了一块地址为AD8500的内存,里边放的值是30,内存模型如下图:

42e27a93202edc65e37a9ac63ef69799.png

执行到add()方法时,程序在栈内存中又开辟了一块地址为AD8600的内存,将num的值30传递进来,此时这块内存里边放的值是30,执行param = 100;后,AD8600中的值变成了100。内存模型如下图:

18dd6b8c9447758c5efe7328de6265ab.png

地址AD8600中用于存放param的值,和存放num的内存没有任何关系,无论你怎么改变param的值,实际改变的是地址为AD8600的内存中的值,而AD8500中的值并未改变,所以num的值也就没有改变。

以上是基本类型参数的传递方式,下来我们讨论一下对象作为参数传递的方式。

先看下边的示例代码:

public class ParameterTransfer {

public static void main(String[] args) {

String[] array = new String[] {"huixin"};

System.out.println("调用reset方法前array中的第0个元素的值是:" + array[0]);

reset(array);

System.out.println("调用reset方法后array中的第0个元素的值是:" + array[0]);

}

public static void reset(String[] param) {

param[0] = "hello, world!";

}

}

运行的结果如下:

调用reset方法前array中的第0个元素的值是:huixin

调用reset方法后array中的第0个元素的值是:hello, world!

当对象作为参数传递时,传递的是对象的引用,也就是对象的地址。下边用内存模型图来说明。

465f72fd3f94d456029e4d168b69309e.png

当程序执行了String[] array = new String[] {"huixin"}后,程序在栈内存中开辟了一块地址编号为AD9500内存空间,用于存放array[0]的引用地址,里边放的值是堆内存中的一个地址,示例中的值为BE2500,可以理解为有一个指针指向了堆内存中的编号为BE2500的地址。堆内存中编号为BE2500的这个地址中存放的才是array[0]的值:huixin。

当程序进入reset方法后,将array的值,也就是对象的引用BE2500传了进来。这时,程序在栈内存中又开辟了一块编号为AD9600的内存空间,里边放的值是传递过来的值,即AD9600。可以理解为栈内存中的编号为AD9600的内存中有一个指针,也指向了堆内存中编号为BE2500的内存地址,如图所示:

200b935fec3b41a8cebfde88b46b7bc5.png

这样一来,栈内存AD9500和AD9600(即array[0]和param的值)都指向了编号为BE2500的堆内存。

在reset方法中将param的值修改为hello, world!后,内存模型如下图所示:

e0dd6d7984f00be138980c6bb4eb2e83.png

改变对象param的值实际上是改变param这个栈内存所指向的堆内存中的值。param这个对象在栈内存中的地址是AD9600,里边存放的值是BE2500,所以堆内存BE2500中的值就变成了hello,world!。程序放回main方法之后,堆内存BE2500中的值仍然为hello,world!,main方法中array[0]的值时,从栈内存中找到array[0]的值是BE2500,然后去堆内存中找编号为BE2500的内存,里边的值是hello,world!。所以main方法中打印出来的值就变成了hello,world!

无论是基本类型作为参数传递,还是对象作为参数传递,实际上传递的都是值,只是值的的形式不用而已。第一个示例中用基本类型作为参数传递时,将栈内存中的值30传递到了add方法中。第二个示例中用对象作为参数传递时,将栈内存中的值BE2500传递到了reset方法中。当用对象作为参数传递时,真正的值是放在堆内存中的,传递的是栈内存中的值,而栈内存中存放的是堆内存的地址,所以传递的就是堆内存的地址。这就是它们的区别。

在Java语言中,对于哪些数据类型是按值传递,哪些数据类型是按址传递都作出了硬性规定,如下所示:

l  按值传递的数据类型:八种基本数据类型和String(这样理解可以,但是事实上String也是传递的地址,只是string对象和其他对象是不同的,string对象是不能被改变的,内容改变就会产生新对象)。

ll   按址传递的数据类型:除String以外的所有复合数据类型,包括数组、类和接口

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值