无效方法后更新Java变量

时间:2019-03-09 00:52:16

标签: java methods parameter-passing pass-by-reference pass-by-value

我对Java的工作方式有些困惑,我知道以下几点是正确的:

public static void main(String[] args) {
    int c=0;
    changeC(c);
    System.out.println(c); // 0
}

public static void changeC(int c) {
    c++;
}

我们知道c的输出0是因为changeC方法不会更改原始的c

现在我正在看solution on Leetcode,它似乎遵循类似的概念。

代码如下:

public int numIslands(char[][] grid) {
    int count=0;
    for(int i=0;i<grid.length;i++)
        for(int j=0;j<grid[0].length;j++){
            if(grid[i][j]=='1'){
                dfsFill(grid,i,j);
                count++;
            }
        }
    return count;
}
private void dfsFill(char[][] grid,int i, int j){
    if(i>=0 && j>=0 && i<grid.length && j<grid[0].length&&grid[i][j]=='1'){
        grid[i][j]='0';
        dfsFill(grid, i + 1, j);
        dfsFill(grid, i - 1, j);
        dfsFill(grid, i, j + 1);
        dfsFill(grid, i, j - 1);
    }
}

在这种情况下,网格被传递给void函数dfsFills()。然而,无论dfsFill()grid的作用如何,grid函数中的numIslands()也会被更新。

为什么这与我的第一个示例有所不同?是一种通过引用,另一种通过值吗?

2 个答案:

答案 0 :(得分:1)

它不是传递引用,因为无论方法内部发生什么,调用者的变量Array ( [0] => 5c832a3fc6335 [1] => 5c832a3f89d5b [2] => 5c832a3fec3a6 [3] => 5c832a3fb080d [4] => 5c832a3fdbe90 ) 仍指向它在调用之前所做的同一对象。

区别在于Array ( [0] => 5c832a3fc6335 [1] => 5c832a3fb080d [2] => 5c832a3f89d5b [3] => 5c832a3fdbe90 [4] => 5c832a3fec3a6 ) 是可变对象(数组),因此该方法可能导致grid内部的状态发生变化。由于两个地方(呼叫者和被呼叫者)都看同一个对象,因此他们都将看到在此所做的更改。

Java中的所有内容都按值传递。但是除了原始类型之外,传递的“值”是指向对象的指针。因此,如果该对象的状态是可变的,则需要小心。

“按引用传递”表示该方法可以更改调用方的变量以指向其他对象。这是不可能的。在您的示例中,您可以确保例如grid并非突然grid或它的长度已更改。

答案 1 :(得分:0)

是,不是。

是的,因为这是JVM内部工作的方式。像int这样的原始参数是通过复制其值来传递的,而其他Stringint[]这样的其他参数都是通过复制引用(指向堆中的实际对象)传递的。

否,因为即使使用java.lang.Integer,它是int的盒装类型,并且通过复制引用来传递时,您也会看到完全相同的行为。实际上,在Java中根本没有使用“按值传递”和“按引用传递”之类的术语。

void foo() {
  Integer i = 0;
  bar(i);
  assert i == 0;
}

void bar(Integer i) {
  i++;
}

关键事实是i++意味着i = i + 1,它使用i1产生一个新的int,将名称i与新的int,并丢弃先前的int值,而不是直接更改先前的int

诸如array[0]++people.age++之类的事物以相同的方式工作。它将age的属性people与新的int绑定。它会更改属性age,但不会影响int本身