观察下面程序段,写出最终输出,并说明理由。
public static void main(String[] args) {
int a = 10;
int b = 20;
System.out.println("a:"+a+",b:"+b); //a = 10,b = 20
change(a,b);
System.out.println("a:"+a+",b:"+b); //?
}
public static void change(int a,int b) { //a = 10, b= 20
System.out.println("a:"+a+",b:"+b); //a = 10,b = 20
a = b; //a = 20
b = a + b; //b = 40
System.out.println("a:"+a+",b:"+b); //a = 20, b = 40
}
输出结果:
a:10,b:20
a:10,b:20
a:20,b:40
a:10,b:20
分析走一波:
- 主函数先压进栈,然后分配int型变量a、b并赋值,此时a = 10、b = 20。
- change方法压进栈,change方法中定义两个变量a、b,将主方法中的a、b的值传递给形参,此时两组a、b值相等(a = 10、b = 20),但不是同一组a、b。对change方法中的值进行改变,此时change方法中的a = 20、b = 40,控制台打印输出。
- change方法调用结束后弹栈,方法中的局部变量a、b随之消失,最终主方法中的输出a = 10、b = 20。
图解如下:
再看一段:
public static void main(String[] args) {
int[] arr = {1,2,3,4,5};
change(arr);
System.out.println(arr[1]);
}
public static void change(int[] arr) {
for (int i = 0; i < arr.length; i++) {
if (arr[i] % 2 == 0) {
arr[i] *= 2;
}
}
}
输出结果:
4
分析走一波:
- 主函数先压进栈,然后分配int型数组的首地址,分配五块空间,初始化各空间对应的值。
- change方法压进栈,将主方法中的数组arr首地址传递给形参,可通过地址寻找实体。对数组进行遍历,满足判断条件的值*2,遍历结束。
- change方法调用结束后弹栈,arr[1]中的值被改变,最终主方法中的输出4。
总结:
- 基本数据类型的值传递,不改变原始值,因为方法调用后就会弹栈,局部变量随之消失。
- 引用数据类型的值传递,改变原始值,因为即使方法弹栈,但是堆内存数组对象还在,可以通过地址继续访问。
补充问题:JAVA中到底是传递值还是传址?
Java中只有传值,因为地址值也是值(面试遇到的话就这么回答,因为支持者是高司令(Java之父))