java參數傳遞

網絡上有太多關於JAVA參數傳遞是傳值仍是傳引用的討論,其實大可能是概念不清,混淆視聽。從程序運行的角度來看,參數傳遞,只有傳值,從不傳遞其它的東西。只不過值的內容有多是數據,也有多是一個內存地址。網絡

  Java中的數據類型有兩大類,即基本類型(primitive types), 共有8種,包括int, short, long, byte, float, double, boolean, char,存在於棧(Stack)中。另外一種暫稱爲對象類型,包括Integer, String, Double等相應基本數據類型的包裝類,以及其餘全部JAVA自帶和用戶自定義的類,這些類數據所有存在於堆中(Heap),以下圖所示。app

   對象類型的數據不一樣於基本類型的數據,咱們所定義的對象變量並非對象實例自己,而是對象的一個引用(reference)地址,該內存地址用來定位該對象實例在HEAP中的位置。對象實例自己和對象的引用分別保存在HEAP和STACK中,對象引用和對象實例之間的關係比如遙控器和電視機之間的關係,在房間走動的時候裏,你只需拿着遙控器就能夠控制電視機,而沒必要帶着電視機。並且,即便沒有電視機,遙控器也能夠獨立存在,也就是說你能夠定義一個對象類型的變量,可是能夠暫時不和一個對象實例關聯。多個對象引用也能夠指向同一個對象實例。spa

 


      Heap(堆)       Stack(棧)
 JVM中的功能            內存數據區                    內存指令區
 存儲數據  對象實例  基本數據類型, 指令代碼,常量,對象的引用地址

 

下面咱們來看看幾個例子,您就會更加明白。orm

例子1:對象

public class Test {
public static void changeValue(int i) {
i=2;
System.out.println("during test: i = " + i);
}
public static void main(String[] args) {
int i = 1;
System.out.println("Before test: i = " + i);
changeValue(i);
System.out.println("After test: i = " + i);
}
}
  運行結果:
Before test: i = 1
during test: i = 2
After test: i = 1內存

不難看出,雖然在 changeValue(int i)方法中改變了傳進來的參數的值,但對這個參數源變量自己並無影響。其內部原理是,main方法裏的變量和changeValue方法的參數是兩個不一樣的變量,以參數形式傳遞簡單類型的變量時,其實是將參數的值做了一個拷貝傳進方法的,那麼在方法裏再怎麼改變其值,其結果都是隻改變了拷貝的值,而不是源值。ci

例子2:string

public class Test {
public static void test(StringBuffer str) {
str.append(", World!");
}
public static void main(String[] args) {
StringBuffer string = new StringBuffer("Hello");
test(string);
System.out.println(string);
}
}
  運行結果:
Hello, World!it

   在這個例子裏,彷佛變量string被「改變」了。但其實改變的並非string變量自己,也就是說string保存的內存地址並無被改變,改變的是它所指向的對象實例。內部原理是這樣的,在main方法裏定義了一個對象引用string,而且把它和一個對象實例關聯new StringBuffer。方法調用的時候,string所保存的對象實例的內存地址傳遞給了test方法的對象引用參數str,這時就有兩個對象引用變量指向同一個對象實例。這兩個對象引用均可以對該對象實例進行操做,操做結果都有效,所以在test方法執行完以後,對象實例的內容已經被改變了,這個時候再經過main方法裏的string引用去查看對象實例的內容,看到的就是改變以後的內容。table

例子3:

public class Test {
public static void test(String str) {
str = "World";
}
public static void main(String[] args) {
String string = "Hello";
test(string);
System.out.println(string);
}
}

運行結果:

Hello。

這個結果和上面結果矛盾嗎?一點也不矛盾。在這個例子中,參數傳遞過程和上個例子徹底同樣,可是在test方法裏並非對原來指向的對象實例進行操做,而是把str指向了另一個對象實例,固然對原來的對象實例毫無影響。

相關文章
相關標籤/搜索