Java中参数传递

情景引入

我们先来看下面这个栗子

//冒泡排序
public static void BubbleSort(int[] arr) {
		if(arr==null || arr.length<2)
			return;
		for(int end=arr.length-1;end>0;end--) {
			for(int i=0;i<end;i++) {
				if(arr[i]>arr[i+1])
					//交换
					swap(arr[i],arr[i+1]);
			}
		}
	}


private static void swap(int x,int y) {
		int cup;
		cup=x;
		x=y;
		y=cup;
	}

public static void main(String[] args) {
		int[] arr= {1,2,4,7,3,9};
		BubbleSort(arr);
		for(int i=0;i<arr.length;i++) {
			System.out.println(arr[i]);
		}
	}

这个栗子相信大家都不陌生,这里打印出来的结果是:

1,2,4,7,3,9

我们发现结果完全没改变,其实问题就是出现在了swap()方法上
我们对swap作下修改:

private static void swap(int[] arr, int x,int y) {
		int cup=arr[x];
		arr[x]=arr[y];
		arr[y]=cup;
	}

打印结果:

1,2,3,4,7,9

在新的swap方法中,我们传入了数组的地址,就可以运行出来正确的结果了。接下来我们来研究下Java中参数的传递。


参数传递的秘密

所谓参数有实际参数和形式参数之分,函数列表中的叫做形式参数,在实际调用中它们会被实际参数传递。但是编译器并不知道每次调用的实际参数是什么,于是写编译器的高手就出个办法,让实际参数按照一定顺序放到一个大家都可以找得到的地方,以此作为方法调用的一种约定。所谓“没有规矩,不成方圆”,有了这个规矩,大家协作起来就容易多了。这个公共数据区,现在编译器的选择通常是“栈”,而所谓的顺序就是形式参数声明的顺序。显然,程序运行的过程中,作为实际参数的变量可能遍布于内存的各个位置,而并不一定要老老实实的呆在栈里。为了守“规矩”,程序只好将变量复制一份到栈中,也就是通常所说的将参数压入栈中。
参数传递的秘密就是复制,栈中的参数是实参的副本,这就是所谓的值传递。

  • 所有的参数传递都是传值,区别在于传的是基本数据类型还是引用
  • 所有的参数传递都会在程序运行栈上新分配一个值的复制品
  • 引用变量之间复制的是地址,副本和传入的指向同一块内存
  • 基本数据类型之间复制的是内存中的值(直接量)

public static void value(int x) {
		x=1;
	}
	
public static void value(int[] arr,int i) {
		arr[i]=1;
	}

public static void main(String[] args) {
		int x=7;
		int[] arr= {7};
		value(x);
		System.out.println(x);//打印结果:7
		value(arr,0);
		System.out.println(arr[0]);//打印结果:1
	}

第一个例子的值没有变化,因为只是给x的副本赋值为1,与x本身没有任何关系
第二个例子的值有变化,因为传入了数组,是引用类型,复制的另一份变量和传入的数组指向的是同一块内存,所以改变这个副本的值,会改变原来的内存。

小结

Java中参数传递只有按值传递。所谓按值传递可以简单理解为实参的复制,区别在于复制的实参是基本数据类似还是引用类型。

猜你喜欢

转载自blog.csdn.net/weixin_40288381/article/details/87798960