前言
首先声明一点,Java中的所有数据类型无论是基本数据类型还是引用数据类型,都只有传值操作,没有传址操作。
一、Java中的数据类型
Java中的数据类型主要包括:基本数据类型和引用数据类型。其中基本数据类型是存储在栈内存中的(使用完毕后,立即消失),引用数据类型可以看做是两部分—1.引用部分 2.引用所指向的部分。引用部分存储在栈内存中,引用所指向的部分存储在堆内存中。
我们通过一个交换数据的例子来解释Java中并不存在传址操作。
二、交换数据
1.不成功交换
代码如下:
public class SwapStudy {
public static void swap(int a,int b) {
int temp = a;
a = b;
b = temp;
System.out.println("方法中的a:"+a+" 方法中的b:"+b);
}
public static void main(String[] args) {
int a = 3;
int b = 4;
swap(a,b);
System.out.println("交换后的:a"+a+" 交换后的b:"+b);
}
}
运行结果
结果如下:
方法中的a:4 方法中的b:3
交换后的a:3 交换后的b:4
可以发现a和b在swap()方法中成功交换了,但是在主函数中未成功交换。这个交换过程是个传值过程。
原因解释
主函数和swap()方法中的a和b都是基本数据类型,他们存储在栈内存中,我们在main函数中调用了swap()方法,这一步我们大家都知道只是将a,b的数值传递进去了。而随着swap()方法的结束,它方法栈中的数据都会消失不见,这就是为什么交换不成功的原因。
2.成功交换
代码如下:
class DataWrap{
int a;
int b;
}
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
DataWrap dw = new DataWrap();
dw.a = 3;
dw.b = 4;
swap(dw);
System.out.println("主函数交换过的dw.a:"+dw.a);
System.out.println("主函数交换过的dw.b:"+dw.b);
}
public static void swap(DataWrap dw) {
int temp = dw.a;
dw.a = dw.b;
dw.b = temp;
System.out.println("方法中的dw.a:"+dw.a);
System.out.println("方法中的dw.b:"+dw.b);
}
}
运行结果
结果如下:
方法中的dw.a:4
方法中的dw.b:3
主函数交换过的dw.a:4
主函数交换过的dw.b:3
可以发现a和b在主函数中成功交换了,但是这个交换过程仍然是个传值过程。
原因解释
这次交换过程中a和b是DataWrap类中的成员变量。在主函数中创建了DataWrap类的实例—dw。dw存储在栈内存中,指向堆内存中的a和b。虽然“swap(dw);”这个语句传递的是一个地址,并且在swap()方法中接收到的地址也是指向堆内存中的a和b,但是这仍然不是传址操作。
第一:主函数中的dw与方法中dw虽然都指向相同的地址,但是二者在栈内存中的地址不一样。
第二:当将方法中的dw地址设为NULL,如果主函数中的地址也变成NULL,则就是传址,反之就是传值,只不过传的是地址值。
代码如下:
class DataWrap{
int a;
int b;
}
public class Deliver {
public static void Main(String[] args) {
// TODO Auto-generated method stub
DataWrap dw = new DataWrap();
dw.a = 3;
dw.b = 4;
swap(dw);
System.out.println("主函数交换过的dw.a:"+dw.a);
System.out.println("主函数交换过的dw.b:"+dw.b);
System.out.println("主函数中dw指向的地址:"+dw);
}
public static void swap(DataWrap dw) {
int temp = dw.a;
dw.a = dw.b;
dw.b = temp;
System.out.println("方法中的dw.a:"+dw.a);
System.out.println("方法中的dw.b:"+dw.b);
dw = null;
System.out.println("方法中的dw指向的地址:"+dw);
}
}
运行结果
结果如下:
方法中的dw.a:4
方法中的dw.b:3
方法中的dw指向的地址:null
主函数交换过的dw.a:4
主函数交换过的dw.b:3
主函数中dw指向的地址:Method.DataWrap@5594a1b5
通过结果很明显看到,虽然方法中的dw不指向堆内存中的a和b,但是主函数中的dw仍然指向堆内存。