1. 程式人生 > 其它 >Java 變數 形參和實參

Java 變數 形參和實參

技術標籤:java

舉例
1. 比如你定義一個函式public static int add(int a,int b),這裡的a和b就是形參。
2. 當你進行函式呼叫的時候,add(1,2),這裡的1和2就是實參。
3. 簡單來說就是進行函式呼叫的時候需要實參從主函式中傳給被呼叫函式中的形參,這樣函式才可以執行,實參和形參起到一個橋樑的作用。
/*-- 例子 --*/
  1. public class Test {

  2. public static void main(String[] args) {

  3. Integer a = 1;

  4. Integer b = 2;

  5. System.out.println("a 和 b 的原始的值:"+a+" "+b);

  6. swap(a,b);

  7. System.out.println("a 和 b 的現在的值:"+a+" "+b);

  8. }

  9. private static void swap(Integer a, Integer b) {

  10. // TODO Auto-generated method stub

  11. }

  12. }

Java 形參和實參的區別:

形參:就是形式引數,用於定義方法的時候使用的引數,是用來接收呼叫者傳遞的引數的。 形參只有在方法被呼叫的時候,虛擬機器才會分配記憶體單元,在方法呼叫結束之後便會釋放所分配的記憶體單元。 因此,形參只在方法內部有效,所以針對引用物件的改動也無法影響到方法外。

實參:就是實際引數,用於呼叫時傳遞給方法的引數。實參在傳遞給別的方法之前是要被預先賦值的。 在本例中 swap 方法 的numa, numb 就是形參,傳遞給 swap 方法的 a,b 就是實參

注意:在值傳遞呼叫過程中,只能把實參傳遞給形參,而不能把形參的值反向作用到實參上。在函式呼叫過程中,形參的值發生改變,而實參的值不會發生改變。而在引用傳遞呼叫的機制中,實際上是將實參引用的地址傳遞給了形參,所以任何發生在形參上的改變也會發生在實參變數上。

值傳遞和引用傳遞

JAVA的資料型別——分為兩大類:基本型別 和 物件型別。相應的,變數也有兩種型別:基本型別 和 引用型別。

基本型別的變數儲存原始值,即它代表的值就是數值本身, 原始值一般對應在記憶體上的棧區;而引用型別的變數儲存引用值,引用值指向記憶體空間的地址。代表了某個物件的引用,而不是物件本身。物件本身存放在這個引用值所表示的地址的位置。被引用的物件對應記憶體上的堆記憶體區。

基本型別包括:byte,short,int,long,char,float,double,boolean這八大基本資料型別; 引用型別包括:類型別介面型別陣列。

變數的基本型別和引用型別的區別:基本資料型別在宣告時系統就給它分配空間

  1. int a;

  2. //雖然沒有賦值,但宣告的時候虛擬機器就會 分配 4位元組 的記憶體區域,

  3. //而引用資料型別不同,它宣告時只給變數分配了引用空間,而不分配資料空間:

  4. String str;

  5. //宣告的時候沒有分配資料空間,只有 4byte 的引用大小,

  6. //在棧區,而在堆記憶體區域沒有任何分配

  7. str.length();

  8. //這個操作就會報錯,因為堆記憶體上還沒有分配記憶體區域,而 a = 1; 這個操作就不會報錯。

值傳遞:方法呼叫時,實際引數把它的值傳遞給對應的形式引數,函式接收的是原始值的一個copy, 此時記憶體中存在兩個相等的基本型別,即實際引數和形式引數,後面方法中的操作都是對形參這個值的修改,不影響實際引數的值。

引用傳遞:也稱為地址傳遞、址傳遞。方法呼叫時,實際引數的引用(地址,而不是引數的值)被傳遞給方法中相對應的形式引數,函式接收的是原始值的記憶體地址在方法執行中,形參和實參內容相同,指向同一塊記憶體地址,方法執行中對引用的操作將會影響到實際物件。

注意:類似的 String, Integer, Float, Double, Short, Byte, Long, Character等基本包裝型別類。因為他們本身沒有提供方法去改變內部的值,例如 Integer內部有一個 value 來記錄 int基本型別的值,但是沒有提供修改它的方法,而且 也是 final型別的,無法通過 常規手段更改。所以雖然他們是引用型別的,但是可以認為它是值傳遞,這個也只是認為,事實上還是引用傳遞、址傳遞。

程式碼完善:

  1. private static void swap(Integer numa, Integer numb){

  2. int tmp = numa.intValue();

  3. try{

  4. Field field = Integer.class.getDeclaredField("value");

  5. field.setAccessible(true);

  6. field.set(numa, numb);

  7. field.set(numb, new Integer(tmp));

  8. }catch(Exception e){

  9. e.printStackTrace();

  10. }

  11. }

Integer的裝箱操作,當給 Integer.value 賦值 int時,JVM 檢測到 int不是Integer型別,需要裝箱,才執行了Integer.valueOf()方法。而 field.set(numb,new Integer(tmp)) 設定的 是Integer型別了,就不會再拆箱後再裝箱。