欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

一文淺析Java中的值傳遞

 更新時(shí)間:2023年08月01日 08:56:00   作者:HuskySir  
今天在解決一個(gè)問(wèn)題時(shí),程序總是不能輸出正確值,分析邏輯思路沒(méi)問(wèn)題后,發(fā)現(xiàn)原來(lái)是由于函數(shù)傳遞導(dǎo)致了這個(gè)情況,下面我們就來(lái)看看Java中的值傳遞到底是什么情況吧

LeetCode 113

問(wèn)題:給你二叉樹(shù)的根節(jié)點(diǎn)root和一個(gè)整數(shù)目標(biāo)和targetSum,找出所有 從根節(jié)點(diǎn)到葉子節(jié)點(diǎn) 路徑總和等于給定目標(biāo)和的路徑。

示例

輸入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22

輸出:[[5,4,11,2],[5,8,4,5]]

我的代碼如下

class Solution {
    public void traversal(TreeNode root, int count, List<List<Integer>> res, List<Integer> path) {
        path.add(root.val);
        if (root.left == null && root.right == null) {
            if (count - root.val == 0) {
                res.add(path);
            }
            return;
        }
?
        if (root.left != null) {
            traversal(root.left, count - root.val, res, path);
            path.remove(path.size() - 1);
        }
        if (root.right != null) {
            traversal(root.right, count - root.val, res, path);
            path.remove(path.size() - 1);
        }
    }
?
    public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
        List<List<Integer>> res = new ArrayList<>();
        List<Integer> path = new ArrayList<>();
        if (root == null) return res;
        traversal(root, targetSum, res, path);
?
        return res;
    }
}

該題的思路是采用遞歸,traversal函數(shù)內(nèi)root是當(dāng)前樹(shù)的根節(jié)點(diǎn),count是目標(biāo)值,res是存儲(chǔ)結(jié)果,path是路徑。該代碼對(duì)于示例的輸入輸出為

輸入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22

輸出:[[5],[5]]

經(jīng)過(guò)排查最終問(wèn)題在于代碼中的add方法

原代碼部分內(nèi)容為

if (root.left == null && root.right == null) {
    if (count - root.val == 0) {
        res.add(path);
    }
    return;
}

該部分內(nèi)容需要改為

if (root.left == null && root.right == null) {
    if (count - root.val == 0) {
        res.add(new ArrayList(path));
    }
    return;
}

此時(shí)所有代碼對(duì)于示例的輸入輸出為

輸入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22

輸出:[[5,4,11,2],[5,8,4,5]]

在java中,存在8大基本數(shù)據(jù)類(lèi)型,且均有對(duì)應(yīng)的包裝類(lèi)

數(shù)據(jù)類(lèi)型占用位數(shù)默認(rèn)值包裝類(lèi)
byte(字節(jié)型)80Byte
short(短整型)160Short
int(整型)320Integer
long(長(zhǎng)整型)640.0lLong
float(浮點(diǎn)型)320.0fFloat
double(雙精度浮點(diǎn)型)640.0dDouble
char(字符型)16"/u0000"Character
boolean(布爾型)1falseBoolean

在java中,函數(shù)傳遞只有值傳遞,是指在調(diào)用函數(shù)時(shí),將實(shí)際參數(shù)復(fù)制一份傳遞給函數(shù),這樣在函數(shù)中修改參數(shù)(形參)時(shí),不會(huì)影響到實(shí)際參數(shù)。

基本數(shù)據(jù)類(lèi)型的值傳遞

測(cè)試類(lèi)

public class TestClass {
    public static void test(int value) {
        value = 2;
        System.out.println("形參value的值:" + value);
    }
?
    public static void main(String[] args) {
        int value = 1;
        System.out.println("調(diào)用函數(shù)前value的值:" + value);
        test(value);
        System.out.println("調(diào)用函數(shù)后value的值:" + value);
    }
}

結(jié)果為

調(diào)用函數(shù)前value的值:1
形參value的值:2
調(diào)用函數(shù)后value的值:1

結(jié)論:可以看到,int類(lèi)型的value初始為1,調(diào)用函數(shù)后,value仍然為1,基本數(shù)據(jù)類(lèi)型在函數(shù)中修改參數(shù)(形參)時(shí)不會(huì)影響到實(shí)參的值。

引用數(shù)據(jù)類(lèi)型的值傳遞

類(lèi)TreeNode

public class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
?
    TreeNode() {
    }
?
    TreeNode(int val) {
        this.val = val;
    }
?
    TreeNode(int val, TreeNode left, TreeNode right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}

測(cè)試類(lèi)1

public class TestClass {
    public static void test(TreeNode node) {
        node.val = 2;
        System.out.println("形參node的val值:" + node.val);
    }
?
    public static void main(String[] args) {
        TreeNode node = new TreeNode(1);
        System.out.println("調(diào)用函數(shù)前node的val值:" + node.val);
        test(node);
        System.out.println("調(diào)用函數(shù)后node的val值:" + node.val);
    }
}

結(jié)果為

調(diào)用函數(shù)前node的val值:1
形參node的val值:2
調(diào)用函數(shù)后node的val值:2

結(jié)論:可以看到,TreeNode類(lèi)型的node對(duì)象的val值初始為1,調(diào)用函數(shù)后,node對(duì)象的val值被修改為2,引用數(shù)據(jù)類(lèi)型在函數(shù)中修改參數(shù)(形參)時(shí)影響到了實(shí)參的值。

現(xiàn)在看另一個(gè)示例

測(cè)試類(lèi)2

public class TestClass {
    public static void test(TreeNode node) {
        node = new TreeNode(2);
        System.out.println("形參node的val值:" + node.val);
    }
?
    public static void main(String[] args) {
        TreeNode node = new TreeNode(1);
        System.out.println("調(diào)用函數(shù)前node的val值:" + node.val);
        test(node);
        System.out.println("調(diào)用函數(shù)后node的val值:" + node.val);
    }
}

結(jié)果為

調(diào)用函數(shù)前node的val值:1
形參node的val值:2
調(diào)用函數(shù)后node的val值:1

結(jié)論:可以看到,TreeNode類(lèi)型的node對(duì)象的val值初始為1,調(diào)用函數(shù)后,node對(duì)象的val值仍然為1,引用數(shù)據(jù)類(lèi)型在函數(shù)中修改參數(shù)(形參)時(shí)未影響到實(shí)參的值。

那么,為什么會(huì)出現(xiàn)這種問(wèn)題呢?

首先,在JAVA中,函數(shù)傳遞都是采用值傳遞,實(shí)際參數(shù)都會(huì)被復(fù)制一份給到函數(shù)的形式參數(shù),所以形式參數(shù)的變化不會(huì)影響到實(shí)際參數(shù),基本數(shù)據(jù)類(lèi)型的值傳遞示例可以發(fā)現(xiàn)這個(gè)性質(zhì)。但引用數(shù)據(jù)類(lèi)型的值傳遞為什么會(huì)出現(xiàn)修改形式參數(shù)的值有時(shí)會(huì)影響到實(shí)際參數(shù),而有時(shí)又不會(huì)影響到實(shí)際參數(shù)呢?其實(shí)引用數(shù)據(jù)類(lèi)型傳遞的內(nèi)容也會(huì)被復(fù)制一份給到函數(shù)的形式參數(shù),這個(gè)內(nèi)容類(lèi)似C++中的地址,示例中的node對(duì)象存儲(chǔ)于堆中,雖然形參與實(shí)參是兩份內(nèi)容,但內(nèi)容值相同,都指向堆中相同的對(duì)象,故測(cè)試類(lèi)1在函數(shù)內(nèi)修改對(duì)象值時(shí),函數(shù)外查看時(shí)會(huì)發(fā)現(xiàn)對(duì)象值已被修改。測(cè)試類(lèi)2在函數(shù)內(nèi)重新構(gòu)造了一個(gè)對(duì)象node,在堆中申請(qǐng)了一個(gè)新對(duì)象(新對(duì)象與原對(duì)象val值不相同),讓形參指向這個(gè)對(duì)象,所以不會(huì)影響到原對(duì)象node的值。測(cè)試類(lèi)1與測(cè)試類(lèi)2的區(qū)別在于引用數(shù)據(jù)類(lèi)型的指向?qū)ο蟀l(fā)生了變化。

以下代碼可驗(yàn)證上述分析

測(cè)試類(lèi)1

public class TestClass {
    public static void test(TreeNode node) {
        System.out.println("test:node" + node);
        node.val = 2;
        System.out.println("test:node" + node);
        System.out.println("形參node的val值:" + node.val);
    }
?
    public static void main(String[] args) {
        TreeNode node = new TreeNode(1);
        System.out.println("調(diào)用函數(shù)前node的val值:" + node.val);
        System.out.println("main node:" + node);
        test(node);
        System.out.println("調(diào)用函數(shù)后node的val值:" + node.val);
        System.out.println("main node:" + node);
    }
}

結(jié)果為

調(diào)用函數(shù)前node的val值:1
main node:TreeNode@1540e19d
test:nodeTreeNode@1540e19d
test:nodeTreeNode@1540e19d
形參node的val值:2
調(diào)用函數(shù)后node的val值:2
main node:TreeNode@1540e19d

測(cè)試類(lèi)2

public class TestClass {
    public static void test(TreeNode node) {
        System.out.println("test:node" + node);
        node = new TreeNode(2);
        System.out.println("test:node" + node);
        System.out.println("形參node的val值:" + node.val);
    }
?
    public static void main(String[] args) {
        TreeNode node = new TreeNode(1);
        System.out.println("調(diào)用函數(shù)前node的val值:" + node.val);
        System.out.println("main node:" + node);
        test(node);
        System.out.println("調(diào)用函數(shù)后node的val值:" + node.val);
        System.out.println("main node:" + node);
    }
}

結(jié)果為

調(diào)用函數(shù)前node的val值:1
main node:TreeNode@1540e19d
test:nodeTreeNode@1540e19d
test:nodeTreeNode@677327b6
形參node的val值:2
調(diào)用函數(shù)后node的val值:1
main node:TreeNode@1540e19d

對(duì)于測(cè)試類(lèi)1,形參和實(shí)參都是指向相同的對(duì)象,所以利用形參修改對(duì)象的值,實(shí)參指向的對(duì)象的值發(fā)生改變。對(duì)于測(cè)試類(lèi)2,形參在函數(shù)開(kāi)始和實(shí)參指向相同的對(duì)象,讓其指向新的對(duì)象后,實(shí)參指向的對(duì)象的值不會(huì)發(fā)生改變。簡(jiǎn)要說(shuō),測(cè)試類(lèi)1形參復(fù)制了實(shí)參的地址,修改了地址對(duì)應(yīng)的對(duì)象值,但并未修改地址值,測(cè)試類(lèi)2形參復(fù)制了實(shí)參的地址,并修改了地址值,但并未修改原地址值對(duì)應(yīng)的對(duì)象值。

有了目前的結(jié)論,可以理解為什么res.add()函數(shù)內(nèi)path修改為new ArrayList(path)就可代碼運(yùn)行成功。因?yàn)槲业膒ath類(lèi)型為L(zhǎng)ist<Integer>,為引用數(shù)據(jù)類(lèi)型,且path的值一直在發(fā)生變化。隨著遞歸代碼的運(yùn)行,path的值發(fā)生變化,res內(nèi)最初的List<Integer>值會(huì)發(fā)生變化(就是path的值)。但將path修改為new ArrayList(path)后,是在堆中新構(gòu)造了對(duì)象,并指向該對(duì)象,原對(duì)象的變化不會(huì)影響到該對(duì)象的值,那么res內(nèi)List<Integer>值就不會(huì)發(fā)生變化。

listList.add()方法直接傳入list1

import java.util.ArrayList;
import java.util.List;
?
public class TestClass {
    public static void main(String[] args) {
        List<List<Integer>> listList = new ArrayList<>();
        List<Integer> list1 = new ArrayList<>();
        list1.add(1);
        listList.add(list1);  //直接add list1
        List<Integer> list2 = new ArrayList<>();
        list2.add(2);
        listList.add(list2);
        System.out.println("list1改變前");
        for (List<Integer> l : listList) {
            for (Integer i : l) {
                System.out.println(i);
            }
            System.out.println("---");
        }
        list1.set(0, 2);    //將list1的0號(hào)元素改為2
        System.out.println("list1改變后");
        for (List<Integer> l : listList) {
            for (Integer i : l) {
                System.out.println(i);
            }
            System.out.println("---");
        }
    }
}

結(jié)果為

list1改變前
1
---
2
---
list1改變后
2
---
2
---

listList.add()方法重新構(gòu)造新對(duì)象(內(nèi)容與list1相同)

import java.util.ArrayList;
import java.util.List;
?
public class TestClass {
    public static void main(String[] args) {
        List<List<Integer>> listList = new ArrayList<>();
        List<Integer> list1 = new ArrayList<>();
        list1.add(1);
        listList.add(new ArrayList<>(list1)); //構(gòu)造新對(duì)象 再調(diào)用add
        List<Integer> list2 = new ArrayList<>();
        list2.add(2);
        listList.add(list2);
        System.out.println("list1改變前");
        for (List<Integer> l : listList) {
            for (Integer i : l) {
                System.out.println(i);
            }
            System.out.println("---");
        }
        list1.set(0, 2);    //將list1的0號(hào)元素改為2
        System.out.println("list1改變后");
        for (List<Integer> l : listList) {
            for (Integer i : l) {
                System.out.println(i);
            }
            System.out.println("---");
        }
    }
}

結(jié)果為

list1改變前
1
---
2
---
list1改變后
1
---
2
---

到此這篇關(guān)于一文淺析Java中的值傳遞的文章就介紹到這了,更多相關(guān)Java值傳遞內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java排序之冒泡排序的實(shí)現(xiàn)與優(yōu)化

    Java排序之冒泡排序的實(shí)現(xiàn)與優(yōu)化

    冒泡排序是一種簡(jiǎn)單的交換排序。之所以叫做冒泡排序,因?yàn)槲覀兛梢园衙總€(gè)元素當(dāng)成一個(gè)小氣泡,根據(jù)氣泡大小,一步一步移動(dòng)到隊(duì)伍的一端,最后形成一定對(duì)的順序。本文將利用Java實(shí)現(xiàn)冒泡排序,并進(jìn)行一定的優(yōu)化,希望對(duì)大家有所幫助
    2022-11-11
  • Java Springboot如何基于圖片生成下載鏈接

    Java Springboot如何基于圖片生成下載鏈接

    這篇文章主要介紹了Java Springboot如何基于圖片生成下載鏈接,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-03-03
  • 詳解如何解決SSM框架前臺(tái)傳參數(shù)到后臺(tái)亂碼的問(wèn)題

    詳解如何解決SSM框架前臺(tái)傳參數(shù)到后臺(tái)亂碼的問(wèn)題

    這篇文章主要介紹了詳解如何解決SSM框架前臺(tái)傳參數(shù)到后臺(tái)亂碼的問(wèn)題,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-12-12
  • 詳解Java如何優(yōu)雅的實(shí)現(xiàn)字典翻譯

    詳解Java如何優(yōu)雅的實(shí)現(xiàn)字典翻譯

    當(dāng)我們?cè)贘ava應(yīng)用程序中需要對(duì)字典屬性進(jìn)行轉(zhuǎn)換返回給前端時(shí),如何簡(jiǎn)單、方便、并且優(yōu)雅的處理是一個(gè)重要問(wèn)題。在本文中,我們將介紹如何使用Java中的序列化機(jī)制來(lái)優(yōu)雅地實(shí)現(xiàn)字典值的翻譯,從而簡(jiǎn)化開(kāi)發(fā)
    2023-04-04
  • 圖解Springboot集成七牛云并實(shí)現(xiàn)圖片上傳功能過(guò)程

    圖解Springboot集成七牛云并實(shí)現(xiàn)圖片上傳功能過(guò)程

    在實(shí)際開(kāi)發(fā)中 ,基本都會(huì)有應(yīng)用到文件上傳的場(chǎng)景,但隨著或多或少的需求問(wèn)題,之前有在springboot上用過(guò)七牛云實(shí)現(xiàn)圖片上傳,今天因?yàn)槟承┰蛴种匦率褂昧讼缕吲T埔虼讼肟偨Y(jié)下七牛云
    2021-11-11
  • SpringBoot HATEOAS用法簡(jiǎn)介(入門(mén))

    SpringBoot HATEOAS用法簡(jiǎn)介(入門(mén))

    這篇文章主要介紹了SpringBoot HATEOAS用法簡(jiǎn)介(入門(mén)),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • Springboot?整合?RocketMQ?收發(fā)消息的配置過(guò)程

    Springboot?整合?RocketMQ?收發(fā)消息的配置過(guò)程

    這篇文章主要介紹了Springboot?整合?RocketMQ?收發(fā)消息,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-12-12
  • 詳解使用JavaCV/OpenCV抓取并存儲(chǔ)攝像頭圖像

    詳解使用JavaCV/OpenCV抓取并存儲(chǔ)攝像頭圖像

    本篇文章主要介紹了使用JavaCV/OpenCV抓取并存儲(chǔ)攝像頭圖像,實(shí)例分析了使用JavaCV/OpenCV抓取并存儲(chǔ)攝像頭圖像的技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2017-04-04
  • 利用Java實(shí)現(xiàn)解析網(wǎng)頁(yè)中的內(nèi)容

    利用Java實(shí)現(xiàn)解析網(wǎng)頁(yè)中的內(nèi)容

    這篇文章主要為大家詳細(xì)介紹了如何利用Java語(yǔ)言做一個(gè)解析指定網(wǎng)址的網(wǎng)頁(yè)內(nèi)容小應(yīng)用,文中的實(shí)現(xiàn)步驟講解詳細(xì),感興趣的可以嘗試下
    2022-10-10
  • Spring Cloud 的 Hystrix.功能及實(shí)踐詳解

    Spring Cloud 的 Hystrix.功能及實(shí)踐詳解

    這篇文章主要介紹了Spring Cloud 的 Hystrix.功能及實(shí)踐詳解,Hystrix 具備服務(wù)降級(jí)、服務(wù)熔斷、線程和信號(hào)隔離、請(qǐng)求緩存、請(qǐng)求合并以及服務(wù)監(jiān)控等強(qiáng)大功能,需要的朋友可以參考下
    2019-07-07

最新評(píng)論