欢迎访问昆山宝鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 后台管理


新闻资讯

MENU

软件开发知识
原文出处: 刘文哲

我们都知道,在Java中,要领的参数通报永远都是指值通报。让我们来看一看根基范例和荟萃的参数通报在内存中是如何浮现的。

原文链接:https://dzone.com/articles/java-pass-by-reference-or-pass-by-value

在接头Java中参数是如何通报之前,我们有须要先弄清楚Java的变量(主要指的是根基范例和工具)是怎么存储在内存中的。
根基范例一般都存储在仓库中;对付Java工具,实际的工具数据存储在堆中,而工具的指针(指向推中的工具)存储在仓库中。

 

1.png

1.传值 vs 传引用

“传值”和“传引用”别离是什么意思:

  • 传值:当要领参数是值通报时,意味着原参数的一个拷贝被传到了参数内部而不是原始参数,所以任何对付该参数的改变都只会影响这个拷贝值。
  • 传引用:当要领参数是引用通报时,意味着原始参数的引用可能说指针被通报到了要领内部,而不是这个原始参数的内容。
  • 2.在Java中参数是怎么通报的

    在Java中,不管原始参数的范例是什么,参数都是按值通报的。每次当一个要领被执行的时候,劳务派遣管理系统,在仓库中就会为每个参数建设一个拷贝,这个拷贝会被通报到要领内部。

  • 假如原始参数是根基范例,那么在仓库中建设的即是这个参数的简朴拷贝
  • 假如原始参数不是根基范例,那么在仓库中建设的即是指向真正工具数据的新的引用或指针。这个新的引用被通报到要领内部(在这种环境下,有2个引用指向了同一个工具数据)
  • 3.办理迷惑

    在接下来的示例中,我们通过往要领中通报差异范例的参数(根基范例,昆山软件开发,包装类,荟萃类,自界说类),在要领执行完成后去查抄他们是否被修改了来实验证明“在Java中参数通报永远是值通报”。

    根基范例参数

    public static void main(String[] args) {
        int x = 1;
        int y = 2;
        System.out.print("Values of x & y before primitive modification: ");
        System.out.println(" x = " + x + " ; y = " + y );
        modifyPrimitiveTypes(x,y);
        System.out.print("Values of x & y after primitive modification: ");
        System.out.println(" x = " + x + " ; y = " + y );
    }
    private static void modifyPrimitiveTypes(int x, int y)
    {
        x = 5;
        y = 10;
    }

    输出:

    Values of x & y before primitive modification:  x = 1 ; y = 2
    Values of x & y after primitive modification:  x = 1 ; y = 2

    说明:
    x,y这2个参数是根基范例,所以存储在仓库中。当挪用modifyPrimitiveTypes()要领时,在仓库中建设了这2个参数的拷贝(我们就叫它们w,z),实际上是w,z被通报到了要领中。所以原始的参数并没有被通报到要领中,在要领中的任何修改都只浸染于参数的拷贝w,z

    2.png

     

    包装类

    public static void main(String[] args) {
        Integer obj1 = new Integer(1);
        Integer obj2 = new Integer(2);
        System.out.print("Values of obj1 & obj2 before wrapper modification: ");
        System.out.println("obj1 = " + obj1.intValue() + " ; obj2 = " + obj2.intValue());
        modifyWrappers(obj1, obj2);
        System.out.print("Values of obj1 & obj2 after wrapper modification: ");
        System.out.println("obj1 = " + obj1.intValue() + " ; obj2 = " + obj2.intValue());
    }
    private static void modifyWrappers(Integer x, Integer y)
    {
        x = new Integer(5);
        y = new Integer(10);
    }

    输出:

    Values of obj1 & obj2 before wrapper modification: obj1 = 1 ; obj2 = 2
    Values of obj1 & obj2 after wrapper modification: obj1 = 1 ; obj2 = 2

    说明:
    包装类存储在堆中,在仓库中有一个指向它的引用
    当挪用modifyWrappers()要领时,在仓库中为每个引用建设了一个拷贝,这些拷贝被通报到了要领里。任安在要领内里的修改都只是改变了引用的拷贝,昆山软件开发,而不是原始的引用

    3.png

     

    P.S: 假如要领中的表达式为x += 2,x值得改变也不会影响到要领外部,因为包装类是immutable范例的。当他们的state变革时,他们就会建设一个新的实例。假如你想相识更多关于immutable类,可以阅读How to create an immutable class in Java。字符串范例和包装类相似,所以以上的法则对付字符串也有效。

    荟萃范例

    public static void main(String[] args) {
        List<Integer> lstNums = new ArrayList<Integer>();
        lstNums.add(1);
        System.out.println("Size of list before List modification = " + lstNums.size());
        modifyList(lstNums);
        System.out.println("Size of list after List modification = " + lstNums.size());
    }
    private static void modifyList(List<Integer> lstParam)
    {
        lstParam.add(2);
    }

    输出:

    Size of list before List modification = 1
    Size of list after List modification = 2