日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

代碼寫的越急,程序跑得越慢。—— Roy Carlson

時間過得真快,2020已經過去了一半,但是疫情好像還沒有真正的消滅,人們出行還是得帶著口罩,天氣越來越熱,受罪啊。

言歸正傳,都2020年了,居然還有人認為JAVA的參數傳遞方式是引用傳遞,今天我就來講一講java的參數傳遞,好好看,寫的不對的地方,請大聲說出來,反正我也不會改,憋壞了就不好了

基本數據類型傳遞

我們先來看一個普通的例子

package com.ymy.param;

/**
 * @ProjectName: demo
 * @Package: com.ymy.param
 * @ClassName: BaseTypeTest
 * @Author: 流星007
 * @Description: 基本數據類型傳遞
 * csdn:https://blog.csdn.net/qq_33220089
 * 今日頭條:https://www.toutiao.com/c/user/5372182357/#mid=1637641735275523
 * @Date: 2020/7/5 12:52
 * @Version: 1.0
 */
public class BaseTypeTest {

    public static void main(String[] args) {
        int a = 1;
        dosomthing(a);
        System.out.println("主函數a的值 = "+a);

    }

    private static void dosomthing(int a) {
        a = a-1;
        System.out.println("修改過后,a = "+a);

    }
}

1234567891011121314151617181920212223242526272829

這是一個很簡單的一個方法,在主函數main中對變量進行了初始化a=1,然后將a傳遞給dosomthing(),然后再dosomthing中輸出了修改之后的值,最后在主函數中打印a的值,你們覺得這幾句輸出中a的值分別是多少呢?

第一種:修改過后,a = 0主函數a的值 = 1第二種:修改過后,a = 0主函數a的值 = 0第三種:修改過后,a = 1主函數a的值 = 1

想要得到答案的話就得先明白參數傳遞的兩個類型:值傳遞和引用傳遞。

什么是引用傳遞?在C++中,函數參數的傳遞方式有引用傳遞。所謂引用傳遞是指在調用函數時將實際參數的地址傳遞到函數中,那么在函數中對參數所進行的修改,將影響到實際參數。

什么是值傳遞?值傳遞是指在調用函數時將實際參數復制一份傳遞到函數中,這樣在函數中如果對參數進行修改,將不會影響到實際參數。

我們再回過頭來看上面的例子,如果是引用傳遞的話打印結果應該是第二種情況,如果是值傳遞,打印結果應該是第一種情況,所以到底打印的結果是什么呢?

我們一起看一看控制臺輸出

Connected to the target VM, address: '127.0.0.1:59333', transport: 'socket'
修改過后,a = 0
主函數a的值 = 1
Disconnected from the target VM, address: '127.0.0.1:59333', transport: 'socket'

Process finished with exit code 0
123456

這就是第一種情況,很明顯,在dosomthing函數中修改了a的值,但是主函數中的a并沒有受到影響,所以肯定不會是引用傳遞,如果是引用傳遞,主函數的a應該會變成0,只有在參數傳遞的時候將主函數的中參數復制一份給dosomthing,才能在dosomthing中修改a不會對主函數造成影響,所以從基本數據類型來看,java的參數傳遞方式為:值傳遞

這個時候你可能會有疑問了,這只是基本數據類型的傳遞方式,其他的參數類型呢?下面我們一起來看看引用類型和對象類型的傳遞方式。

follow me !!!!!

引用類型傳遞

我們都知道java中的String類型不屬于基本數據類型,它是一個引用類型,也可以說是一個對象,那么它的傳遞方式是什么呢?

我們還是先來看例子

package com.ymy.param;

/**
 * @ProjectName: demo
 * @Package: com.ymy.param
 * @ClassName: StringTypeTest
 * @Author: 流星007
 * @Description: String類型傳遞
 * csdn:https://blog.csdn.net/qq_33220089
 * 今日頭條:https://www.toutiao.com/c/user/5372182357/#mid=1637641735275523
 * @Date: 2020/7/5 14:22
 * @Version: 1.0
 */
public class StringTypeTest {

    public static void main(String[] args) {
        String a = "hello";
        dosomthing(a);
        System.out.println("主函數a的值 = "+a);

    }

    private static void dosomthing(String a) {
        a = a+" bug";
        System.out.println("修改過后,a = "+a);

    }

}

123456789101112131415161718192021222324252627282930

打印結果

修改過后,a = hello bug
主函數a的值 = hello

Process finished with exit code 0
1234

我們發現主函數的a并沒有受到dosomthing函數的影響,所以這并不是引用傳遞,這個時候你說是因為a = a+" bug";這行代碼生成了新的對象,所以才會導致數據不一致,我們先來看看a的賦值情況吧

// class version 52.0 (52)
// access flags 0x21
public class com/ymy/param/StringTypeTest {

  // compiled from: StringTypeTest.java

  // access flags 0x1
  public <init>()V
   L0
    LINENUMBER 14 L0
    ALOAD 0
    INVOKESPECIAL java/lang/Object.<init> ()V
    RETURN
   L1
    LOCALVARIABLE this Lcom/ymy/param/StringTypeTest; L0 L1 0
    MAXSTACK = 1
    MAXLOCALS = 1

  // access flags 0x9
  public static main([Ljava/lang/String;)V
    // parameter  args
   L0
    LINENUMBER 17 L0
    LDC "hello"
    ASTORE 1
   L1
    LINENUMBER 18 L1
    ALOAD 1
    INVOKESTATIC com/ymy/param/StringTypeTest.dosomthing (Ljava/lang/String;)V
   L2
    LINENUMBER 19 L2
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    NEW java/lang/StringBuilder
    DUP
    INVOKESPECIAL java/lang/StringBuilder.<init> ()V
    LDC "\u4e3b\u51fd\u6570a\u7684\u503c = "
    INVOKEVIRTUAL java/lang/StringBuilder.Append (Ljava/lang/String;)Ljava/lang/StringBuilder;
    ALOAD 1
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
    INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
   L3
    LINENUMBER 21 L3
    RETURN
   L4
    LOCALVARIABLE args [Ljava/lang/String; L0 L4 0
    LOCALVARIABLE a Ljava/lang/String; L1 L4 1
    MAXSTACK = 3
    MAXLOCALS = 2

  // access flags 0xA
  private static dosomthing(Ljava/lang/String;)V
    // parameter  a
   L0
    LINENUMBER 24 L0
    NEW java/lang/StringBuilder
    DUP
    INVOKESPECIAL java/lang/StringBuilder.<init> ()V
    ALOAD 0
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
    LDC " bug"
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
    INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
    ASTORE 0
   L1
    LINENUMBER 25 L1
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    NEW java/lang/StringBuilder
    DUP
    INVOKESPECIAL java/lang/StringBuilder.<init> ()V
    LDC "\u4fee\u6539\u8fc7\u540e\uff0ca = "
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
    ALOAD 0
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
    INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
   L2
    LINENUMBER 27 L2
    RETURN
   L3
    LOCALVARIABLE a Ljava/lang/String; L0 L3 0
    MAXSTACK = 3
    MAXLOCALS = 1
}

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485

這是上面代碼的字節碼代碼,我們可以清楚的看到a在賦值的時候都調用了StringBuilder的同String方法,現在我們來看看這個神奇的同String方法。

@Override
    public String toString() {
        // Create a copy, don't share the array
        return new String(value, 0, count);
    }
12345

這是StringBuilder中的toString方法,確實是new了一個新的對象,就算是a變成了一個新的對象,如果是引用傳遞,主函數的a就不會受影響嗎?這點我會講完對象類型傳遞之后在進行講解,請繼續往下看。

對象類型傳遞

其實上面的兩種其實很好區分,很多人都知道是值傳遞,很多人說java的傳遞方式是引用傳遞的原因就是出自這里:傳遞的參數為對象

有些人看到對象傳遞的時候會改變主函數的值,就認為java的參數傳遞是引用傳遞,有些人又因為基本數據類型不會對主函數的值造成修改,所以他們的結論是:基本數據類型為值傳遞;對象類型為引用傳遞,想法很好,那我們現在一起來解開對象傳遞的神秘面紗,它到底是引用傳遞還是值傳遞呢?

go go go !!!!

還是老規矩,我們一起來看一個例子

package com.ymy.param.vo;

/**
 * @ProjectName: demo
 * @Package: com.ymy.param.vo
 * @ClassName: LolVo
 * @Author: 流星007
 * @Description: lol英雄屬性
 * csdn:https://blog.csdn.net/qq_33220089
 * 今日頭條:https://www.toutiao.com/c/user/5372182357/#mid=1637641735275523
 * @Date: 2020/7/5 15:11
 * @Version: 1.0
 */
public class LolVo {

    /**
     * 姓名
     */
    private String name;

    /**
     * 職業
     */
    private String profession;


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getProfession() {
        return profession;
    }

    public void setProfession(String profession) {
        this.profession = profession;
    }

    @Override
    public String toString() {
        return "LolVo{" +
                "name='" + name + ''' +
                ", profession='" + profession + ''' +
                '}';
    }
}

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
package com.ymy.param;

import com.ymy.param.vo.LolVo;

/**
 * @ProjectName: demo
 * @Package: com.ymy.param
 * @ClassName: ObjectTypeTest
 * @Author: 流星007
 * @Description: 對象類型傳遞
 * csdn:https://blog.csdn.net/qq_33220089
 * 今日頭條:https://www.toutiao.com/c/user/5372182357/#mid=1637641735275523
 * @Date: 2020/7/5 15:16
 * @Version: 1.0
 */
public class ObjectTypeTest {

    public static void main(String[] args) {
        LolVo lolVo = new LolVo();
        lolVo.setName("無極劍圣");
        lolVo.setProfession("刺客");
        dosomthing(lolVo);
        System.out.println("主函數 lolVo = "+lolVo);

    }

    private static void dosomthing(LolVo lolVo) {
        lolVo.setProfession("戰士");
        System.out.println("dosomthing lolVo = "+lolVo);

    }


}

1234567891011121314151617181920212223242526272829303132333435

結果如下:

dosomthing lolVo = LolVo{name='無極劍圣', profession='戰士'}
主函數 lolVo = LolVo{name='無極劍圣', profession='戰士'}

Process finished with exit code 0
1234

主函數中劍圣的職業是刺客,在dosomthing中將他修改成戰士,我們發現主函數中劍圣的職業也被修改成戰士了,顯然這符合引用傳遞的條件,被調用方修改會影響到調用方也就是主函數,所以這個時候很多人就認為java的對象傳遞的方式為引用傳遞,如果你也是這么認為,那么你就要認真看一下我后面的分析。

我們先來一個否定它是引用傳遞的例子,請看好,不要眨眼

package com.ymy.param;

import com.ymy.param.vo.LolVo;

/**
 * @ProjectName: demo
 * @Package: com.ymy.param
 * @ClassName: ObjectTypeTest
 * @Author: 流星007
 * @Description: 對象類型傳遞
 * csdn:https://blog.csdn.net/qq_33220089
 * 今日頭條:https://www.toutiao.com/c/user/5372182357/#mid=1637641735275523
 * @Date: 2020/7/5 15:16
 * @Version: 1.0
 */
public class ObjectTypeTest {

    public static void main(String[] args) {
        LolVo lolVo = new LolVo();
        lolVo.setName("無極劍圣");
        lolVo.setProfession("刺客");
        dosomthing(lolVo);
        System.out.println("主函數 lolVo = "+lolVo);

    }

    private static void dosomthing(LolVo lolVo) {
        lolVo = new LolVo();
        lolVo.setProfession("戰士");
        System.out.println("dosomthing lolVo = "+lolVo);

    }


}

123456789101112131415161718192021222324252627282930313233343536

做了小小的改動,僅僅只是在dosomthing方法中加了一行代碼:lolVo = new LolVo();

我們再來看運行結果是什么呢?還會和上面一樣嗎?

dosomthing lolVo = LolVo{name='null', profession='戰士'}
主函數 lolVo = LolVo{name='無極劍圣', profession='刺客'}

Process finished with exit code 0
1234

我們發現主函數中劍圣的屬性變回了刺客,并沒有受到dosomthing函數的影響,如果是引用傳遞的話,主函數中劍圣的職業應該是戰士而不是刺客。這是為什么呢?為什么是應用傳遞主函數中劍圣的職業應該是戰士呢?

下面我們一起來分析一波

我們假設對象的傳遞方式為引用傳遞

天真,居然還有人認為java的參數傳遞方式是引用傳遞

 

這是堆棧中的信息,當我們將對象lolVo傳遞給dosomthing的時候,是克隆了一個對象出來還是原來的那個對象呢?我們知道,不管傳遞的是不是它本身,值都是內存的地址引用,我們現在先假設主函數沒有復制,是直接將lolVo傳遞給了dosomthing,那圖形應該是什么樣的呢?

天真,居然還有人認為java的參數傳遞方式是引用傳遞

 

如果是引用傳遞,格式是不是應該是這樣呢?main主函數和dosomthing函數共用一個lolVo,這個時候我們在dosomthing函數中執行了一句:lolVo = new LolVo();那又會變成什么樣呢?

天真,居然還有人認為java的參數傳遞方式是引用傳遞

 

在dosomthing方法中我們new了一個新的LolVo對象,并且將這個新的對象賦值給了lolVo,那是不是代表著main主函數核dosomthing函數中的lolVo應該是一樣的呢,我們再來回顧一下上面的代碼

private static void dosomthing(LolVo lolVo) {
        lolVo = new LolVo();
        lolVo.setProfession("戰士");
        System.out.println("dosomthing lolVo = "+lolVo);

    }
123456

我們做了修改之后,主函數劍圣的職業并沒有修改成戰士,所以,說java是引用傳遞是說不通的,那我們再來看看它正確的流程應該是什么樣的呢?

天真,居然還有人認為java的參數傳遞方式是引用傳遞

 

盡管dosomthing對參數的修改會影響調用方,但是它還是屬于值傳遞,會影響調用方是因為java轉遞的時候拷貝的是對象的引用地址。

舉個栗子:比如某公司開發了一套員工的內部管理系統,有一個管理員的賬號,你把這個賬號給了你的同事,他直接使用你這個賬號,這就是引用傳遞,如果你是在用戶管理中添加了一條管理員的用戶,再將這個賬號給你的同事,這就是值傳遞,還需要解釋一下,為什么值傳遞會影響調用方,如果你給的賬號,你同事改了用戶名稱,這對你是不是沒有影響,但如果他手抖把員工全刪了,你這邊還能看到員工信息嗎?就是這個道理,lolVo引用地址相當于管理員賬號,系統內的功能相當于LolVo對象,你修改自己的賬號對別人當然沒有影響,但是你把系統搞沒了,你覺得有影響嗎?這就是為什么java的參數傳遞方式為值傳遞卻能影響調用方。

總結

如果還有人和你說java的參數傳遞是引用傳遞的話,請他來看一下我這篇博客,我把他勸退一下。

分享到:
標簽:java
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定