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