【问题标题】:Java Reference pass to methodsJava 引用传递给方法
【发布时间】:2014-01-19 15:50:35
【问题描述】:

我有一个问题。我有下一个代码示例:

class Test{
    static void change(String s){
        s = "newString";
    }
    public static void main(String args[]){
        String s = "String";
        change(s);
        System.out.print(s);
    }
}

我看到结果是“字符串”。 现在我有以下代码:

class A{
    int a;
    static void change(A a){
       a.a = 10;
    }   
    public static void main(String[] args){
        A a = new A();
        a.a = 5;
        change(a);
        System.out.print(a.a);
    }
}

这以 10 结束。我不明白为什么?这两个不是参考吗?为什么不是第一个代码输出:“newString”?

【问题讨论】:

    标签: java reference


    【解决方案1】:

    这里的区别在于第一个例子中:

    static void change(String s){
        s = "newString";
    }
    

    您重新分配局部变量s 以指向新的String。这对s 之前指向的String 没有影响,并且在方法change() 之外没有影响。

    第二种情况

    static void change(A a){
       a.a = 10;
    }  
    

    您正在修改引用 a 指向的 A 的实例,因此当您从方法返回时,此更改仍然存在。

    【讨论】:

      【解决方案2】:

      Java 按值传递对象引用,因此您不能重新影响作为参数传递的对象。这就是您在第一个示例中看到的内容。

      当然,您可以修改传递对象的内容。这就是您在第二个示例中看到的内容。

      【讨论】:

        【解决方案3】:

        在 String 的情况下,引用 s 是一个本地副本,因此更改它没有任何作用。

        在int 的情况下,您使用的是对包含另一个字段的A 的引用。当您更改该字段时,您并没有更改副本。

        相当于在方法中做a = new A();之类的东西,也不会改变原来的。

        【讨论】:

          【解决方案4】:

          在第一种情况下,方法change(String s) 正在修改原始引用的副本。

          在第二种情况下,方法change(A a)是修改引用指向的变量,不一样。方法中使用的引用a是一个副本,而不是它指向的变量a.a。

          【讨论】:

            【解决方案5】:

            Java is Pass by Value

            因此,在第一种情况下,当您在 change 中获得 s 时,您并没有获得实际的引用,而是获得了引用的副本,因此分配新值不会影响旧值。

            在第二种情况下,您传递了A 的实例,在这种情况下,您将获得引用a 的副本,但您拥有该实例中实际值的句柄。由于 a 包含一个 int a,当您更改 int a 的值时,它会影响实际值。

            为了澄清更多,在第二种情况下,如果你这样做了

            change(A a){
               a = new A();
               a.a = 100;
            }
            

            它不会将您传递的原始a 更改为从main() 更改

            【讨论】:

              【解决方案6】:

              Java 是按值传递而不是按引用传递。这意味着在方法中

              void changeVer1(Something val){
                  val = new Something("else");
              }
              

              val 是 changeVer1 方法的 local 变量,它是您用作方法参数的引用的副本。这意味着当你这样做时

              val = new Something("Else");
              

              您正在更改此本地副本的 值,因此这不会更改您用作此方法参数的“原始”引用的值。


              现在让我们看看这个方法的其他版本

              void changeVer2(Something val){
                  val.someField = 42;
              }
              

              由于val 是您传递的引用的副本,它将与原始引用保持相同的对象,并且该对象的状态 的每次更改都将通过原始引用可见。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2016-12-31
                • 2015-10-31
                • 1970-01-01
                • 1970-01-01
                • 2013-10-04
                • 2012-02-09
                相关资源
                最近更新 更多