Java-自定义swap函数交换两个对象时出现的问题分析

开发环境:在PopStar课设中要求写一个swap函数来进行两个对象的交换,便于在冒泡排序中使用,由于本人在写代码时没顾及太多,所以项目一遍过,没出现任何问题。而后续给同学修改代码时出现了一些懵逼的情况。

实验要求:自定义swap(Star preStar,Star nextStar)函数实现两个star的交换

star的属性:

	/* 泡泡糖在 10 * 10阵列中坐标位置 */
	private Position position = null;

	/* 泡泡糖类型(颜色) */
	private StarType type = null;

正文:

这里我通过三个方法实现交换过程(首先排除掉直接等于的做法)。

第一种

我们先创建临时泡泡糖保存star1的属性,然后让star1指向新的泡泡糖,并将star2的属性设置为自己的,star2则是将临时泡泡糖的属性设置给自己, 看起来很正常的交换。然而,结果却是:

就是说,在swap中,我star1和star2的确交换了,但是在main函数中为什么没有交换呢。那我们在看看第二种做法:

第二种

该做法是调用了本类中下发的copy方法:

非常简单明了的复制对象的方法。

那么运行结果如何呢?

仍然是在函数内部发生了变化,函数外面不受影响。

 

再看看第三种做法:

第三种:

运行结果:

成功交换了,为什么呢?

现在我们回到C语言的基础上理解一下

C语言中在传参的时候有值传递和址传递两种,

值传递 void test(int a){}

址传递 void test(int *a){}

我们知道,当在函数内部对形参进行修改的时候,值传递这种方式是不会影响到实参本身的,因为在传入test函数的时候实参只是将值复制了一下传给了形参a,所以无论如何是影响不到原实参的。而址传递中,test函数修改的是内存中的数据,会直接影响到实参的值。

 

将此观念引入到java中,java取消了址传递,也就是说,java只有值传递。

那么当我们将star1传入swap时,实现原理也应该和C语言一样。

原本star1引用对象。当将star1传入到swap函数时,此时复制了一个star1声明(下方的star1 则是star1的复制品),也就是说,在swap中操作的全是star1 ,那么就好解释上述三种情况了。

第一种,我们让star1 引用了一个新的star实例,即:

那么无论对star1 怎么操作都不会对star1 产生影响,所以在swap函数内部star1和star2的确做出了交换,然而交换的是两个新的对象,而不是原始的star1和star2.

那么第二种做法也同理,不做赘述。

第三种方法是正确的。因为 star1 和star1引用的都是一个实例,就是说无论对star1 还是star1来设置属性都是对一个实例对象操作,所以自然就会改变main中的star1和star2.