歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Java 參數傳遞概述

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

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

對象類型的數據不同於基本類型的數據,我們所定義的對象變量並不是對象實例本身,而是對象的一個引用(reference)地址,該內存地址用來定位該對象實例在HEAP中的位置。對象實例本身和對象的引用分別保存在HEAP和STACK中,對象引用和對象實例之間的關系好比遙控器和電視機之間的關系,在房間走動的時候裡,你只需拿著遙控器就可以控制電視機,而不必帶著電視機。而且,即使沒有電視機,遙控器也可以獨立存在,也就是說你可以定義一個對象類型的變量,但是可以暫時不和一個對象實例關聯。多個對象引用也可以指向同一個對象實例。

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

下面我們來看看幾個例子,您就會更加明白。
 
例子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方法的參數是兩個不同的變量,以參數形式傳遞簡單類型的變量時,實際上是將參數的值作了一個拷貝傳進方法的,那麼在方法裡再怎麼改變其值,其結果都是只改變了拷貝的值,而不是源值。
 
例子2:
 
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!
 
  在這個例子裡,似乎變量string被“改變”了。但其實改變的並不是string變量本身,也就是說string保存的內存地址並沒有被改變,改變的是它所指向的對象實例。內部原理是這樣的,在main方法裡定義了一個對象引用string,並且把它和一個對象實例關聯new StringBuffer。方法調用的時候,string所保存的對象實例的內存地址傳遞給了test方法的對象引用參數str,這時就有兩個對象引用變量指向同一個對象實例。這兩個對象引用都可以對該對象實例進行操作,操作結果都有效,因此在test方法執行完之後,對象實例的內容已經被改變了,這個時候再通過main方法裡的string引用去查看對象實例的內容,看到的就是改變之後的內容。
 
例子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指向了另外一個對象實例,當然對原來的對象實例毫無影響。

Java 8 中 HashMap 的性能提升 http://www.linuxidc.com/Linux/2014-04/100868.htm

Java 8 的 Nashorn 引擎 http://www.linuxidc.com/Linux/2014-03/98880.htm

Java 8簡明教程 http://www.linuxidc.com/Linux/2014-03/98754.htm

Copyright © Linux教程網 All Rights Reserved