文章目录
- 实现两数交换
- 方法一、(数组的方式进行交换)
- 方法二、(对象的方式进行交换)
- 总结
实现两数交换
实现两数交换,没有办法通过直接传递数字达到交换的结果,定义的int型变量是被存储在栈空间上的,在栈空间上的是无法直接通过交换达到想要的效果的,因为在栈空间上定义是变量本质上都是属于局部变量,当我们将两个数传递给交换方法时,方法内的形参用于接收,此时相当于再重新创建了两个数字,也就是说,此时在程序中创建了4个变量。
public static void func3(int a , int b) {int tmp = a;a = b;b = tmp;
}public static void main(String[] args) {int aa = 1;int bb = 2;func3(aa, bb);}
此时我们再创建一个中间变量tmp用于辅助交换
当程序将方法func3执行完了之后,回到main方法里面,此时两个变量交换了,但是交换的是变量a和变量b而非变量aa和变量bb,当方法func3执行完毕后,变量a和变量b会被程序回收,此时变量aa和变量bb依旧是原来的数字并没有进行交换,因此func3方法并没有实际意义上的交换,仅仅是将局部变量a和b进行交换了并没有影响到我们真正要交换的变量。
在C语言中,想要达到两数交换的效果可以通过地址进行交换,但是在Java里面没有地址的说法,那么我们可以换一个角度想,在Java里面包含有引用型变量和基本数据类型变量,引用型变量是存储在堆空间上的,通过在栈空间上开辟一块空间用于存储堆空间的地址,这块空间有一个名字叫做引用型变量,引用型变量和C语言的地址有异曲同工之妙,引用可以看作是存储内容的地址,拿Java的数组来说,数组名就是一个引用,通过数组名就可以找到存储在堆空间上的数组进而对其进行操作。
因此我们想要通过Java实现两数交换可以通过引用,将引用传递给方法,在方法内直接通过引用对变量进行操作交换
而基本数据类型,使用基本数据类型创建的变量都是存储在栈空间上的,我们没有办法拿到栈空间的地址,而Java也没有地址的说法,因此需要将存储在栈空间上的变量通过方法进行交换,根本不可能,这也就意味着基本数据类型是无法做到两数交换的
方法一、(数组的方式进行交换)
public static void swap(int[] array ) {int tmp = array[0];array[0] = array[1];array[1] = tmp;}public static void main(String[] args) {int[] array = {1 , 2};System.out.println(array[0] + " " + array[1]);swap(array);System.out.println(array[0] + " " + array[1]);}
数字1和2通过数组的方式存储在堆空间上,将数组的引用传递给方法,即便是方法使用形参进行接受,方法通过形参直接操作数组的数据,并没有改变形参的指向,此时是实参和形参同时指向同一个堆空间,也就是对形参对数组的操作等同于实参对数组的操作。
但是如果在方法内改变形参的指向,那么此时在方法内做的任何操作都是无用功,当在改变指向的同时,形参就再也无法直接拿到实参堆空间上的地址了,改变指向之后就会指向堆空间上新的地址,这个时候两块地址之间是没有任何联系的,因此对于新空间的操作是无法影响到实参的堆空间的,因此在实现两数交换传递实参的时候,方法内要避免更改形参的指向,
public static void func1(int[] array) {array = new int[]{1 , 2};}public static void func2(int[] array) {array[0] = 10;}
方法func1修改了形参的指向,因此在方法内对于形参的任何操作都不会影响到实参
方法func2没有修改形参的指向,而是直接对数组进行操作,那么此时形参对数组的操作就等同于实参对数组的操作
方法二、(对象的方式进行交换)
既然引用型数据类型可以进行交换,那么自定义引用类型肯定也可以,我们可以定义一个类,其中只定义一个成员变量
public class Myvalue {public int a = 20;public Myvalue(int a) {this.a = a;}
}
再通过实例化对象,使用构造方法定义两个数据,此时我们就可以得到了两个互不相干的数据,两个对象之间是没有任何联系的,则对象内的数据也是没有任何联系的。我们再创建一个方法,形参是类类型的变量,用于存储实参传递过去的引用
public static void swap(Myvalue myvalue , Myvalue myvalue1){}
在方法内直接通过引用操作数据,注意要避免修改形参的指向,否则方法内所做的一切都是无用功
class my {public static void swap(Myvalue myvalue , Myvalue myvalue1){int tmp = myvalue.a;myvalue.a = myvalue1.a;myvalue1.a = tmp;}public static void main1(String[] args) {Myvalue myvalue = new Myvalue(10);Myvalue myvalue1 = new Myvalue(20);System.out.println(myvalue.a + "" + myvalue1.a);swap(myvalue , myvalue1);System.out.println(myvalue.a + "" + myvalue1.a);}
总结
在Java中,因为没有地址的说法,因此无法直接通过传地址达到两数交换的效果,Java中的基本数据类型是存储在栈空间上的,而栈空间的地址是无法直接拿到的,在栈空间上存储的地址都是局部变量,当方法结束后变量就会被JVM直接回收,这也就意味着只要是存储在栈空间上的变量都无法做到两数交换。
而我们可以通过引用型数据类型的引用型变量可以拿到存储在堆空间上面的数据,引用型变量本质上是存储堆空间的地址,因此可以通过引用改变数据,而非像基本数据类型那般只能改变自己的数据,一旦改变的是自己本身的数据那么就没有办法再操作实参的数据,只有通过一个数据去改变另外一个数据才能够达到传递给方法后形参操作数据等同于实参操作数据的效果,这也就类似于将引用传递给方法,只要方法内不改变形参的指向,那么在方法内的任何操作都可以当做是实参在进行操作。