技术控

    今日:68| 主题:49270
收藏本版 (1)
最新软件应用技术尽在掌握

[其他] 【Java深入学习系列】二. 值传递Or引用传递?

[复制链接]
正在输入◇ 发表于 2016-10-16 17:06:05
143 2

立即注册CoLaBug.com会员,免费获得投稿人的专业资料,享用更多功能,玩转个人品牌!

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
我们来看一个新手甚至写了多年Java的朋友都可能不是十分确定的问题:
  在Java方法传参时,究竟是引用传递还是值传递?
  为了说明问题, 我给出一个非常简单的class定义:
  [code]public class Foo {
String attribute;
Foo(String s) {
this.attribute = s;
}
void setAttribute(String s) {
this.attribute = s;
}
String getAttribute() {
return this.attribute;
}
}
[/code]  下面在阐明观点时,可能会多次用到该类。
  关于Java里值传递还是引用传递,至少从表现形式上来看,两种观点都有支撑的论据。下面我来一一分析:
  观点1:引用传递

  理由如下:
  先看一段代码
  [code]public class Main {
public static void modifyReference(Foo c){
c.setAttribute("c"); // line DDD
}

public static void main(String[] args) {
Foo fooRef = new Foo("a"); // line AAA
modifyReference(fooRef); // line BBB
System.out.println(fooRef.getAttribute()); // 输出 c
}
}
[/code]  上述示例,输出结果为”c”,而不是”a”, 也就是传入的fooRef里的属性被修改了,发生了side-effect。
   我们在 line AAA 处新创建了一个Object Foo并将其引用 fooRef 在 line BBB 处传给了方法 modifyReference() 的参数 cRef , 该方法内部处理后, fooRef 指向的Object中的值从”a”变成了”c”, 而引用 fooRef 还是那个引用, 因此,我们是否可以认为,在 line BBB 处发生了引用传递?
  先留着疑问,我们继续往下看。
  观点2:值传递

  继续看一段代码
  [code]public class Main {
public static void changeReference(Foo aRef){
Foo bRef = new Foo("b");
aRef = bRef; // line EEE
}

public static void main(String[] args) {
Foo fooRef = new Foo("a"); // line AAA
changeReference(fooRef); // line BBB
System.out.println(fooRef.getAttribute()); // 输出 a
}
}
[/code]  上述示例,输出结果为”a”, 而不是”b”, 即对传入的fooRef内部的change并没有影响外部的传入前的值。
   我们在 line AAA 处新创建了一个Object Foo并将其引用 fooRef 在 line EEE 处传给了方法 changeReference() 的参数 aRef , 该方法内部引用 aRef 在 line DDD 处被重新赋值。如果是引用传递,那么引用 aRef 在 line EEE 处已经被指向了新的Object, 输出应该为 "b" 才对,事实上是怎样的呢?事实上输出了 "a" ,也就是说 changeReference() 方法改变了传入引用所指对象的值。
  观点1和观点2的输出结果多少会让人有些困惑,别急,我们继续往下看。
  深入分析

  为了详细分析这个问题,把上述两段代码合起来:
  [code]public class Main {
public static void modifyReference(Foo cRef){
cRef.setAttribute("c"); // line DDD
}
public static void changeReference(Foo aRef){
Foo bRef = new Foo("b"); // line FFF
aRef = bRef; // line EEE
}

public static void main(String[] args) {
Foo fooRef = new Foo("a"); // line AAA
changeReference(fooRef); // line BBB
System.out.println(fooRef.getAttribute()); // 输出 a

modifyReference(fooRef); // line CCC
System.out.println(fooRef.getAttribute()); // 输出 c


}
}
[/code]  下面来深入内部来详细分析一下引用和Object内部的变化。
  来看下面图示:
      ① Line AAA, 申明一个名叫 fooRef ,类型为 Foo 的引用,并见其分配给一个新的包含属性值为 "f" 的对象,该对象类型为 Foo 。
   [code]Foo fooRef = new Foo("a"); // line AAA
[/code]     
【Java深入学习系列】二. 值传递Or引用传递?-1 (public,return,Java,朋友)

   ② Line DDD, 方法内部,申明了一个 Foo 类型的名为 aRef 的引用,且 aRef 被初始化为 null 。
  [code]void changeReference(Foo a);
[/code]

【Java深入学习系列】二. 值传递Or引用传递?-2 (public,return,Java,朋友)

   ③ Line CCC, changeReference() 方法被调用后,引用 aRef 被分配给 fooRef 指向的对象。
  [code]changeReference(fooRef);
[/code]
1234下一页
友荐云推荐




上一篇:Continue Network Fetching Even When App Goes to Background
下一篇:备忘下:如何给chromium提交patch
酷辣虫提示酷辣虫禁止发表任何与中华人民共和国法律有抵触的内容!所有内容由用户发布,并不代表酷辣虫的观点,酷辣虫无法对用户发布内容真实性提供任何的保证,请自行验证并承担风险与后果。如您有版权、违规等问题,请通过"联系我们"或"违规举报"告知我们处理。

若得其情哀矜勿喜 发表于 2016-10-16 18:08:36
有空一起交流一下
回复 支持 反对

使用道具 举报

yh7jt 发表于 2016-10-31 16:12:37
论坛的帖子越来越有深度了!
回复 支持 反对

使用道具 举报

*滑动验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

我要投稿

推荐阅读

扫码访问 @iTTTTT瑞翔 的微博
回页顶回复上一篇下一篇回列表手机版
手机版/CoLaBug.com ( 粤ICP备05003221号 | 文网文[2010]257号 )|网站地图 酷辣虫

© 2001-2016 Comsenz Inc. Design: Dean. DiscuzFans.

返回顶部 返回列表