Java工程师面试1000题144-方法参数的传递机制

144、看下面程序的执行结果

import java.util.Arrays;

public class Exam4 {
    public static void main(String[] args) {
        int i = 1;
        String str = "hello";
        Integer num = 200;
        int[] arr = {1,2,3,4,5};
        MyData my = new MyData();

        change(i,str,num,arr,my);

        System.out.println("i = " + i);
        System.out.println("str = " + str);
        System.out.println("num = " + num);
        System.out.println("arr = " + Arrays.toString(arr));
        System.out.println("my.a = " + my.a);
    }
    public static void change(int j, String s, Integer n, int[] a, MyData m){
        j += 1;
        s += "world";
        n += 1;
        a[0] += 1;
        m.a += 1;
    }
}
class MyData{
    int a = 10;
}

答案:

i = 1
str = hello
num = 200
arr = [2, 2, 3, 4, 5]
my.a = 11

解析:本题主要考察了方法的传递机制和String、包装类等对象的不可变性。

首先我们先分析一下执行完下面五行代码之后,内存的存储情况是什么样子的。

int i = 1;
String str = "hello";
Integer num = 200;
int[] arr = {1,2,3,4,5};
MyData my = new MyData();

为便于理解,下面我画一个简单的示意图:

i是一个int类型的,又是一个局部变量,直接存储在栈里面;str是一个引用数据类型的数据,指向的是“hello”字符串常量,字符串常量是存储在常量池里面,str存储的是一个内存地址,我们随便写一个值吧0x1234;Integer是一个包装类,因此num也是存储的内存地址,指向的是堆当中的一块内存区域;arr是一个数组,数组名里面存储的是首地址,数组的本体也是存储在堆中,arr中存放也是一个内存地址;MyData也是一个对象,my指向的是对象在堆里面的内存地址。

接下来,程序要开始执行  change(i,str,num,arr,my);了,执行change的时候,JVM也会给change开辟一块内存空间,change方法里面有五个参数,因此这里又会有产生局部变量了,方法的参数传递机制告诉我们:形参是基本数据类型时,传递的是数据值。形参是引用数据类型,传递的是地址值。特殊类型:String、包装类等对象具有不可变性。每一个方法,创建一个栈帧,栈帧存放了当前就方法的数据信息(局部变量),当方法调用完毕,该方法的栈帧就被销毁。参数传递完成之后,内存中的情况会变成下面的样子:

接下来进行下一步操作,执行方法体里面的内容。

j += 1;
s += "world";
n += 1;
a[0] += 1;
m.a += 1;

第一句:j += 1;因此我们要在j变量上进行修改,变为2. 

再看下一句,形参s此时也指向常量池里面的hello,要执行拼接操作,此时会在常量池中产生一个新的对象,就是拼接之后的对象,helloworld,然后再把它赋值给s,因此,此时s不再指向常量池中hello的内存地址了,转而指向helloworld所在的内存地址了,不再是0x1234了。

以此类推,包装类型n也不再指向200所在的堆内存地址0x9090了,转而指向加一之后201的内存地址。

数组是怎么发生变化的呢?由于我们这个例子改变的是元素,通过地址0x8989找到a[0]所在的位置,然后就把a[0]的1改变为了2,后面的几个数字不变。

同样的,我们通过m 0x7878一样可以找到堆中的int a = 10,改变a 的值为11.

每一个方法,创建一个栈帧,栈帧存放了当前就方法的数据信息(局部变量),当方法调用完毕,该方法的栈帧就被销毁。

所以当我们吧change方法执行完之后,就变成了下面的样子,栈帧被销毁了:

由此可见,在堆中有两处的值发生了改变,一个数数组的第一个元素变为了2,一个是MyData的int a = 11.

主方法剩下的,i没有改变,仍然还是1,String str 指向的依旧是hello,num指向的依旧是200所在的地址,arr[0]变为了2,MyData.a变为了11.所以程序执行结果就是下面的了:

i = 1
str = hello
num = 200
arr = [2, 2, 3, 4, 5]
my.a = 11

猜你喜欢

转载自blog.csdn.net/qq_21583077/article/details/88633047