java中参数的传递方式

在java中参数传递只有一种,就是值传递,没有引用传递。
在java中参数传递只有一种,就是值传递,没有引用传递。
在java中参数传递只有一种,就是值传递,没有引用传递。

介绍:
值传递:就是在方法中形参接收的是一个数值,对数值进行的处理。在传递参数的过程中,将数值复制出一份(副本),副本传入形参中,进行处理,原参数并没有产生改变。
引用传递:在方法形参接收的是对象的地址值(也称之为引用),这种操作的结果会影响最终的结果,是通过地址找到原参数进行的一些列操作,并不是对原参数的副本进行的操作。这种参数在c语言中使用,实际就是指针的使用,&a,取到的是a的地址,指向的实际内存空间中a的值进行操作。

那么在java中为什么只有值传递,没有引用传递呢?
下面使用一组例子和内存分析图作下解释。
1.基本数据类型作参数传递

例子如下:

public class Test {
	public static void main(String[] args) {
		int num = 2;
		System.out.println("改变之前的数值是:"+num);
		changeNum(2);
		System.out.println("改变之后的数值是:"+num);
	}
	//改变传入的参数数值的方法
	public static void changeNum(int num){  
		num = num * 2;
	}
	
}
改变之前的数值是:2
改变之后的数值是:2




如上,在类中,我们创建了一个changeNum()方法,用于改变传入参数的值(将其扩大二倍),但是在输出结果,实际都是2,该方法并没有改变其值。好的,由此我们引入程序的内存图并加以解释:


解释:在内存中,num存储的数值是2,然后调用changeNum()方法,将num的值改为4,但是改完的值另开辟了一块存储空间用于存储并不是原存储空间的值(也不是在原存储空间中值上直接覆盖存储),调用完成,由于作用域的不同,我们在main中调用的num依旧是之前的num,其指向的还是原值。



2.对象做参数传递
例子如下

public class Test {
	public static void main(String[] args) {
		Person p = new Person();
		System.out.println("更改之前的值为:"+p.num);
		changeValue(p);
		System.out.println("更改之后的值为:"+p.num);
	}
	
	//改变属性值的方法
	public static void changeValue(Person p){
		p.num=p.num*2;
	}
}
class Person { //人类,仅有一个属性。
	int num = 2;
}
更改之前的值为:2
更改之后的值为:4


如上,创建了一个类Test用于测试对象作为参数的传递方式,创建了一个类Person,里面仅有一个属性num,在Test类中,写了一个
changeValue(),传入的参数是Person类的而对象。
内存分析图:

解释:首先创建Person p 的引用 指向 堆内存中Person的对象,在栈内存中,保存的是堆内存中对象的地址,然后传入changValue()中,进行修改, 实际传入的是对象的地址值,直接对地址值对应的堆内存中的对象进行了操作在main方法,仍然是通过Person p这个引用去寻找堆内存中对象的值,实际已经改变。


下面,再来分析一个特别的例子,string和数组都比较特殊,都不是基本数据类型,而是引用数据类型,更为确切的说,String实际可以看作是一个类;数组属于引用类型,二者都是存储在堆内存中。
例子如下:
public class Test {
	public static void main(String[] args) {
		int[] ch = {0,0,0};   //int类型数组
		String str = "before";  //字符串
		System.out.println("更改之前的为:"+str+"----"+Arrays.toString(ch));
		change(str,ch);
		System.out.println("更改之后的为:"+str+"****"+Arrays.toString(ch));
	}
	 //改变字符串和数组的方法
	public static void change(String str,int[] ch){
		str = "changed";
		ch[1]=1;
	}
}
更改之前的为:before----[0, 0, 0]
更改之后的为:before****[0, 1, 0]
这个例子中,change()方法中传入的参数是一个String和一个int类型数组。
内存分析图:
解释: 调用change()方法时,是将str和ch[ ]的堆空间地址传入,并且在栈内存中开辟了新的地址创建变量(即副本)存放传入的地址,在方法中,执行str = “changed”,这句等价于 str = new String("changed");实际上是在堆内存中重新开辟了一块内存,用于创建一个新的对象存储changed,并且将新内存地址赋值给str;第二个参数传入的也是ch[ ]的堆内存地址,方法中,对ch[1]进行操作,实际上可以看做是  对象名.变量   这个操作,即对地址指向的堆内存对象的属性直接操作,并没有改变其地址值,因此,在main方法中调用String str 和 int[ ]   ch还是指向的原地址的对象,str并没有修改,而ch[ ]已经被修改。

总结:
在java中参数传递只有一种,就是值传递,没有引用传递。
在java中参数传递只有一种,就是值传递,没有引用传递。
在java中参数传递只有一种,就是值传递,没有引用传递。

只是,有一些操作看上去是引用传递改变的,实际传入的是地址值,然后指向内存空间对应对象进行的修改,总之,都是内存中进行的副本进行的修改,有的会直接导致原对象值得改变。






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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值