歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Java 參數傳遞概述

Java 參數傳遞概述

日期:2017/3/1 9:43:57   编辑:Linux編程

網絡上有太多關於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