5

该程序输出 6,但是当我取消注释第 9 行时,输出为 5。为什么?我认为 ba 不应该改变,应该保持 5 为主。

1  class C1{
2      int a=5;

3      public static void main(String args[]){
4          C1 b=new C1();
5          m1(b);
6          System.out.println(b.a);
7      }

8      static void m1(C1 c){
9          //c=new C1();
10         c.a=6;
11    }
12 }
4

6 回答 6

10

当您在 Java 中传递对象时,它们作为引用传递,即方法中引用的对象bmain方法c中的参数m1,它们都指向同一个对象,因此当您将值更改为 6 时,它会反映在main方法中。

现在,当您尝试这样做时,您c = new C1();指向c了一个不同的对象,但b仍指向您在main方法中创建的对象,因此更新的值 6 在 main 方法中不可见,您得到 5。

于 2012-04-24T15:02:04.507 回答
3

您正在向您的方法 m1 传递对 C1 类型对象的引用的副本。

如果您取消注释该行,您将获取该引用并将其指向其他地方(不是原始引用仍指向第一个对象),因此,当您打印 b 的值时,您正在打印的值原始对象,您没有更改。

这个问题有一些很好的答案,你真的应该看看。

Java 是“按引用传递”还是“按值传递”?

于 2012-04-24T15:03:06.087 回答
3

Java 是按值传递的,用通俗的话来说,这意味着当你传递一个参数时,你会创建一个指针变量的副本。对象变量真的应该像 C 中的指针一样读取:这在某种程度上使事情更容易理解,至少在来自 C 世界时(其中 C 仅是按值传递)。

因此,在执行 时c=new C1(),或者通常在执行对 的任何分配时c,您正在使c(以前指向所指向的内存的同一位置b)指向另一个位置。因此,以下c.a=6是对 所指向的对象的成员的赋值,该对象不再c是所指向的对象b

于 2012-04-24T15:09:26.683 回答
1

这是因为 m1(C1 c) 中的 c 是对对象的引用,当您执行 ca=6 时,现在 a 等于该对象中的 6。但是如果你在这个方法中执行 c=new c1() ,c 现在正在引用一个完全新的对象,那么你在这个新对象中执行 ca=6 。之后,你退出方法,另一个 c 对象的值仍然是 5

于 2012-04-24T15:03:46.877 回答
1

您的方法m1(b);在 main 中调用,导致在 m1 中创建的新实例取代 main 方法中已创建的 C1 实例。如果您在 m1 中注释实例化,则 main 中的第一个实例将生效。这是因为在java中对象是通过引用而不是值传递的。

于 2012-04-24T15:06:55.443 回答
1

在 Java 中,除了原始类型之外,所有内容都是通过引用传递的,尽管它说传递引用的副本。

因此,在您的情况下,在第一个实例中,指针 b 和 c 都指向同一个对象,因此更新的值会反映在 main 方法中。

在第二种情况下,当您使 c 指向一个新对象(通过调用 new)时,b 仍然指向在 main 方法中创建的对象,因此更新的值不会反映在 main 方法中,因为 b 和 c 指向两个不同的对象。

于 2012-04-26T03:34:32.207 回答