1. 程式人生 > >Java基礎之引用(String,char[],Integer)總結於牛客網的專項練習題

Java基礎之引用(String,char[],Integer)總結於牛客網的專項練習題

1、String的引用:

下列程式碼執行後的結果為:

public class Test {
public static void main(String[] args) {
    StringBuffer a = new StringBuffer("A"); 
    StringBuffer b = new StringBuffer("B"); 
    operator(a, b); 
    System.out.println(a + "," + b); 
} 
public static void operator(StringBuffer x, StringBuffer y) { 
    x.append(y); y = x; 
}
}

正確答案是:AB,B

解析:

    執行StringBuffer a = newStringBuffer("A");    StringBuffer b = newStringBuffer("B"); 後記憶體中的狀態如下圖所示:
執行
publicstaticvoidoperator(StringBuffer x, StringBuffer y) {     x.append(y); y = x; }進入如下方法後,記憶體中的狀態為:
 x.append(y);這條語句執行後,記憶體的狀態為:
 y = x; 這條語句執行後,記憶體的狀態為:
operator方法執行完畢後記憶體中的狀態為:因為方法執行完畢,區域性變數消除。

由記憶體中的狀態,可以知道最後的結果。可以這麼理解:     a,b是物件的引用,指向堆記憶體。將a,b兩個引用傳給x,y,執行x.append(y)方法之後改變了x 引用指向的堆記憶體的儲存內容,變為了AB。y=x,表示引用y指向了引用x指向的儲存區域,沒有改變引用b指向的儲存空間的內容。所以輸出為:AB,B2、String和char陣列引用的區別與聯絡:輸出正確結果為:
public class Example {
    String str = new String("good");
    char[] ch = { 'a', 'b', 'c' };
 
    public static void main(String args[]) {
        Example ex = new Example();
        ex.change(ex.str, ex.ch);
        System.out.print(ex.str + " and ");
        System.out.print(ex.ch);
    }
 
   public void change(String str, char ch[])      
   {
        str = "test ok";
        ch[0] = 'g';
    }
}
輸出為:good and gbc解答:       概念:java傳參只有按值傳遞(也就是把實參的值拷貝給形參,這個值可以是普通的數值,也可以是地址值),java中的物件只能通過指向它的引用來操作,這個引用本身也是變數,不要與C/C++中的傳值與傳址混淆了,java中沒有顯式的指標。
    分析:change函式被呼叫時,第一個形參str接收了類的成員變數str的值(雖然名稱都是str,但是卻是兩個獨立的String型別的引用變數),注意這兩個str自身都是變數且都指向了堆記憶體中的String物件"good",當我們在change函式內部將str指向了另一個String物件"test ok"後,類的成員變數str仍然保持指向"good",所以最終打印出來就是"good";對於第二個形參ch,它也是接收了類的成員變數ch的值拷貝,這一點和str沒有差別,即兩個ch都指向了字元陣列{ 'a', 'b', 'c' }的首地址,但是ch[0]表示的是字元陣列中'a'的地址,修改了它也就修改了字元陣列的第一個元素,這個改變在change函式返回之後也會存在。所以本題中兩個形參傳參的本質區別在於,修改str只是將形參指向了新的物件,對外部的實參沒有任何影響,而修改ch[0]是實實在在的修改了字元陣列的首元素。
    
擴充套件:
1.可以試驗一下,在Example中再定義一個字元陣列char[] ch2={'d'};然後在change函式中把ch[0] = 'g';這句改成ch=ch2;,那麼就會和str傳參一樣的,
change函式返回後不會對類的成員ch有任何影響。
2.本題和“String類是一個final類,不能被繼承”以及“String底層的字元陣列被宣告為private final char value[];所以其值不能被修改”這些String的特性無關。
擴充套件程式碼:
public class Example {
    String str = new String("good");
    char[] ch = { 'a', 'b', 'c' };
    char[] ch2={'d'};
 
    public static void main(String args[]) {
        Example ex = new Example();
        ex.change(ex.str, ex.ch);
        System.out.print(ex.str + " and ");
        System.out.print(ex.ch);
    }
 
   public void change(String str, char ch[])      
   {
        str = "test ok";
        ch=ch2;
    }
}

輸出為:good and abc3、關於Integer的引用案例:下列程式碼正確輸出結果為:
public class Tester{
public static void main(String[] args){
   Integer var1=new Integer(1);
   Integer var2=var1;
   doSomething(var2);
   System.out.print(var1.intValue());
   System.out.print(var1==var2);
}
public static void doSomething(Integer integer){
    integer=new Integer(2);
    }
}

正確答案為:1true解析:來看一張圖,下邊按照每行來寫出註釋:(1)新建了一個引用變數var,指向了堆記憶體中的1。(2)將引用變數var1複製給var2,使var2也指向了堆記憶體中的1。(3)呼叫doSomething方法,則新建了一個引用變數integer,也指向了堆記憶體中的1。(4)然後執行方法體內容,將integer指向了堆記憶體中的2。則輸出必然為1true。可以看下擴充套件例子:
      當引用物件的內部做了修改,才會影響原物件,如果直接將引用修改了,則對原物件沒有影響,唯一的影響就是:這個被修改的引用,現在不是原來物件的引用,而是新物件的引用。      引用傳遞指的是傳遞的時候,傳遞的是物件的引用。如果對引用的內部成員進行操作,則會直接影響到原物件,但是如果直接把此引用指向了其他物件,那對不起,這個引用從此以後,便與之前的物件沒有任何關係,當前代表的僅僅是新指向的物件。