在java中通过引用传递 - 编辑另一个函数中的值

mar*_*ary 0 java pass-by-reference

为什么以下代码输出等于0?

public class A{


    public static void main(String [] args){

        int a=0;
        foo(a);
        System.out.println(a);
    }

    public static void foo(int a){
        a=78;
    }


}
Run Code Online (Sandbox Code Playgroud)

T.J*_*der 5

它输出0是因为这amain函数中的值.Java 完全是按值传递的,它根本没有传递引用.所以,当你打电话foo时,中的a变量传入foo,不给一个参考a变量.foo然后修改 a参数的值,但这对a变量没有任何影响main.

你可能会听到人们谈论"按价值传递参考"或"参考价值传递",这可能令人困惑,我强烈建议避免像瘟疫这样的术语.:-)但这是他们在谈论的:

在您的示例中,a是一个原语.该a变量包含的值0.但同样,你可以这样做:

 Object a = new Object();
 foo(a);
Run Code Online (Sandbox Code Playgroud)

什么传递到foo现在?没错,当它是一个已传递了同样的事情int:该a.唯一的区别是,现在,该a是一个对象引用.对象引用就像其他任何值一样; 它们告诉JVM对象的数据在内存中.把它们想象成一个大阵列或类似的索引.

那么:

int a = 42;
Run Code Online (Sandbox Code Playgroud)

在内存中给我们这个:

+---------+
|    a    |
+---------+
|   42    |
+---------+

这个

Object a = new Object();
Run Code Online (Sandbox Code Playgroud)

......给我们这个:

+---------+
|    a    |             
+---------+             +-----------------+
| mumble  |------------>| The object data |
+---------+             +-----------------+

重要的是要理解它a仍然只包含一个值,就像它包含一个int或一个float.正是这个值的含义不同,就像inta所持有的值的含义不同于a所持有的值的含义一样float.在对象引用的情况下,值的含义是"对象在那里".

就像你可以拥有多个保存值的变量一样42,你可以拥有多个变量来保存对同一个对象的引用:

int a, b;
a = 42;
b = a;
Run Code Online (Sandbox Code Playgroud)

给我们

+---------+     +---------+
|    a    |     |    b    |
+---------+     +---------+
|   42    |     |   42    |
+---------+     +---------+

等等

Object a, b;
a = new Object();
b = a;
Run Code Online (Sandbox Code Playgroud)

给我们

+----------+     +----------+
|     a    |     |     b    |
+----------+     +----------+
|  mumble  |--+--|  mumble  |
+----------+  |  +----------+
              |
              |
              |    +-----------------+
              +--->| The object data |
                   +-----------------+

a并且b仍然只包含值,如42; 但是该值告诉JVM对象所在的位置,因此它们引用(指向)同一个对象.

再回到foo,当你调用一个函数,传入的参数是完全相同就像另一个变量赋值的变量,所以认为b上面的foo函数参数.

在下面的评论中,您已经询问了数组.数组就像对象 - 或者它们对象; 选择你喜欢的语义.:-)所以:

int[] a;
int[] b;

a = new int[5];
b = a;
Run Code Online (Sandbox Code Playgroud)

给我们:

+----------+     +----------+
|     a    |     |     b    |
+----------+     +----------+
|  mumble  |--+--|  mumble  |
+----------+  |  +----------+
              |
              |
              |    +----------------+
              +--->| The array data |
                   +----------------|
                   | [0]: 0         |
                   | [1]: 0         |
                   | [2]: 0         |
                   | [3]: 0         |
                   | [4]: 0         |
                   +----------------+

所以考虑:

public static final void main(String[] args) {
    int[] a = new int[5];
    foo(a);
    System.out.println(a[0]);
}

void foo(int[] b) {
    b[0] = 42;
}
Run Code Online (Sandbox Code Playgroud)

那打印42.为什么?由于a通入foo,所以bfoo指向相同的数组a指向.您可以使用引用更改对象的状态.请注意,您没有更改值b,您正在更改b引用的东西的状态.

对比:

public static final void main(String[] args) {
    int[] a = new int[5];
    foo(a);
    System.out.println(a[0]);
}

void foo(int[] b) {
    b = new int[5]; // <==== change here
    b[0] = 42;
}
Run Code Online (Sandbox Code Playgroud)

现在它打印0,因为你已经为其分配了一个值(一个新的对象引用)b,这对值所持有的值aa值所引用的值没有影响.