1. 程式人生 > >你真的瞭解JAVA的形參和實參嗎?

你真的瞭解JAVA的形參和實參嗎?

「碼匠筆記」

前幾天在頭條上看到一道經典面試題,引發了一些思考。也是寫這篇文章的導火索。

背景

請看題:

  1. publicclassMain{

  2. publicstaticvoid main(String[] args){

  3. Integer a =1;

  4. Integer b =2;

  5. System.out.println("a="+ a +",b="+ b);

  6.        swap(a, b);

  7. System.out.println("a="+ a +",b="+ b);

  8. }

  9. privatestaticvoid swap(Integer numa,Integer numb){

  10. //請實現

  11. }

  12. }

看到這個題後 瞬間覺得有坑。也覺得為什麼要書寫一個 swap

方法呢?如下實現不是更簡單:

  1. publicstaticvoid main(String[] args){

  2. Integer a =1;

  3. Integer b =2;

  4. System.out.println("a="+ a +",b="+ b);

  5. Integer tmp = a;

  6.        a = b;

  7.        b = tmp;

  8. System.out.println("a="+ a +",b="+ b);

  9. }

輸出:

  1. a=1,b=2

  2. a=2,b=1

完美實現交換。但是請注意,這是一道面試題,要的就是考驗一些知識點。所以還是老老實實的實現 swap方法吧。 有的同學可能會想, Integer 是一個包裝型別,是對Int的裝箱和拆箱操作。其實也是一個物件。既然是物件,直接更改物件的引用不就行了?
思路沒問題,我們首先看看實現:

  1. privatestaticvoid swap(Integer numa,Integer numb){

  2. Integer tmp = numa;

  3.        numa = numb;

  4.        numb = tmp;

  5. System.out.println("numa="+ numa +",numb="+ numb);

  6. }

輸出:

  1. a=1,b=2

  2. numa=2,numb=1

  3. a=1,b=2

不出意外,沒有成功
這是什麼原因呢? 技術老手一看就知道問題出在形參和實參混淆了

JAVA的形參和實參的區別:

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

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

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

值傳遞和引用傳遞

在談 值傳遞引用傳遞之前先了解下 Java的資料型別有哪些

JAVA的資料型別

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; 這個操作就不會報錯。

好了,Java的資料型別說完了,繼續我們的 值傳遞引用傳遞的話題。 先背住一個概念: 基本型別的變數是 值傳遞引用型別的變數 結合前面說的 形參實參

值傳遞

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

引用傳遞

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

  1. staticclassPerson{

  2. int age;

  3. Person(int age){

  4. this.age = age;

  5. }

  6. }

  7. privatestaticvoid test(){

  8. int a =100;

  9.        testValueT(a);

  10. System.out.println("a="+ a);

  11. Person person =newPerson(20);

  12.        testReference(person);

  13. System.out.println("person.age="+ person.age);

  14. }

  15. privatestaticvoid testValueT(int a){

  16.        a =200;

  17. System.out.println("int testValueT a="+ a);

  18. }

  19. privatestaticvoid testReference(Person person){

  20.        person.age =10;

  21. }

輸出:

  1. int testValueT a=200

  2. a=100

  3. person.age=10

看見 值傳遞 a的值並沒有改變,而 引用傳遞的 persion.age已經改變了 有人說

  1. privatestaticvoid testReference(Person

    相關推薦

    真的瞭解JAVA?

    「碼匠筆記」前幾天在頭條上看到一道經典面試題,引發了一些思考。也是寫這篇文章的導火索。背景請看題

    Java中的的區別以及傳值呼叫傳引用呼叫

    原文地址:http://blog.csdn.net/miniminiyu/article/details/52061401  名詞解析: 1.形參:用來接收呼叫該方法時傳遞的引數。只有在被呼叫的時候才分配記憶體空間,一旦呼叫結束,就釋放記憶體空間。因此僅僅在方法內有效

    關於Java中的的區別

    類型 分配 不能 內部使用 rdquo 數量 運行時 常量 使用 形參出現在函數定義中,在整個函數體內都可以使用,離開該函數則不能使用。 實參出現在主調函數中,進入被調函數後,實參變量也不能使用。 形參和實參的功能是作數據傳送。發生函數調用時,主調函數把實參的

    的區別

    返回 pre bsp 類型變量 目的 出現 分配內存 函數定義 class 形參:全稱為"形式參數"是在定義函數名和函數體的時候使用的參數,目的是用來接收調用該函數時傳如的參數. 實參:全稱為"實際參數"是在調用時傳遞個該函數的參數. 形參出現在函數定義中,在整個函數體內都

    cor text nsf 數據 round ans post oat pla 形參出現在函數定義中,在整個函數體內都可以使用, 離開該函數則不能使用。實參出現在主調函數中,進入被調函數後,實參變量也不能使用。 形參和實參的功能是作數據傳送。發生函數調用時, 主調函數把實參的

    3-12

    div war 16px pre 參數 多個 src bsp span # * 號可以有多個參數 *名字也可以自定義 規範 是 *args 按規矩來 *args 接收多個位置參數 轉換成元組 **kwargs 接收N個關

    函數

    函數形參 pan nbsp spa color 形參 print class code def cal(x,y):。。形參 s=x**y 。。x的y次方 return s c=cal(2,3) ..實參 print(c) 函數形參和實參

    JS中的區別

    JS中形參和實參的區別 from:https://blog.csdn.net/qq_33187168/article/details/50346465 形參出現在函式定義中,在整個函式體內都可以使用, 離開該函式則不能使用。 實參出現在主調函式中,進入被調函式後,實參變數也不能使用。

    習題 :任意輸入十個數按大小排序;構造簡單數學運算模組(

    任意輸入十個數字,按從大到小的順序排列   設定減法運算模組: 設定 乘除法混合運算 模組 int num = 3*chufa(num1, num2,num3); 這裡有這句指令,將該結果擴大三倍,40->120 *通過上面兩個程式引出形參和實參的概念: 通俗的來講,

    C語言函式篇(二)

    參引數:形參和實參 ------------------------------- 形參實現一種資料傳入的介面 ,由實參 拷貝 給 形參 拷貝!!!!!!!!!!! 拷貝1: void func(int tmp

    C++中的const限定符(5)——const

    1、當形參有頂層const時,傳給它常量物件或非常量物件都是可以的,這一點複合之前所說的,因為形參的初始值是拷貝了實參的。 2、在定義過載函式時,需要注意:對於形參是否是const的,是無法被編譯器所區分的。 void foo(int i){} void foo(co

    Python的

    形參可以設定引數預設值,設定遵循從右至左原則 例如:fun(x=0,y=1),fun(x,y=1),但不可以是fun(x=1,y) 形參設定可以為數字字串變數、元組列表和字典等任意型別資料,元組列表的的形參是在變數名前加*,字典形參是在變數名前加** 例如:fun(

    C語言第55課初始

    ·第55課初始形參和實參 ·例子:自定義冪函式 #include<stdlib.h> //自行實現pow函式 //求第一個引數的n次冪 double power(double,int);//函式原型

    函式返回值作為存在的問題以及的區別

    一、問題描述 若已定義的函式有返回值,則以下關於該函式呼叫的敘述中錯誤的是( D ) (A)函式呼叫可以作為獨立的語句存在。 (B)函式呼叫可以作為一個函式的實參。 (C)函式呼叫可以出現在表示式中。 (D)函式呼叫可以作為一個函式的形參。 解析:函式返回值存在暫存器

    函式特點

    1. 形參變數只有在被呼叫時才分配記憶體單元,在呼叫結束時,即刻釋放所分配的記憶體單元。因此,形參只有在函式內部有效。函式呼叫結束返回主調函式後則不能再使用該形參變數。 2. 實參可以是常量、變數、表示式、函式等,無論實參是何種型別的量,在進行函式呼叫時,它們都必須具有確

    C++函式——const

        頂層const: 表示任意的物件是常量。      底層const: 與指標和引用等複合型別有關。     對指標而言, 頂層const表示指標本身是個常量, 而底層const表示指標所指的物件是一個常量。 int i = 22; const

    python獲得變數的名稱,獲得傳)的名稱

    1.需求和例子 需求:獲得變數的名稱 實現例子: aaa = '23asa' bbb = 'kjljl2' loc = locals() def get_variable_name(variable): print loc for key

    c語言中的區別?

    形式引數和實際引數 函式的引數分為形參和實參兩種。在本小節中,進一步介紹形參、實參的特點和兩者的關係。形參出現在函式定義中,在整個函式體內都可以使用,離開該函式則不能使用。實參出現在主調函式中,進入被調函式後,實參變數也不能使用。形參和實參的功能是作資料傳送。發生函式呼叫

    值型別引用型別,,傳值傳引用

        C# 中有兩種型別:引用型別和值型別。引用型別的變數儲存對其資料(物件)的引用(地址),而值型別的變數直接包含其資料(副本)。     對於引用型別,兩種變數可引用同一物件;因此,

    [C#] 函式呼叫之間加冒號

    看到下面的語法,其他語言都沒見過這種語法 int GetValue(string prompt, int min, int max) { int result; do { result = SnapsEngine.R