文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Java方法传参时采用哪种传递

2023-06-17 04:41

关注

这篇文章给大家介绍Java方法传参时采用哪种传递,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

我们来看一个新手甚至写了多年Java的朋友都可能不是十分确定的问题:

在Java方法传参时,究竟是引用传递还是值传递?

为了说明问题, 我给出一个非常简单的class定义:

public class Foo {   String attribute;   Foo(String s) {     this.attribute = s;   }   void setAttribute(String s) {     this.attribute = s;   }   String getAttribute() {     return this.attribute;   } }

下面在阐明观点时,可能会多次用到该类。

关于Java里值传递还是引用传递,至少从表现形式上来看,两种观点都有支撑的论据。下面我来一一分析:

观点1:引用传递

理由如下:先看一段代码

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   } }

上述示例,输出结果为"c",而不是"c"。

我们在line AAA处新创建了一个Object Foo并将其引用fooRef在line  BBB处传给了方法modifyReference()的参数cRef, 该方法内部处理后,fooRef指向的Object中的值从"a"变成了"c",  而引用fooRef还是那个引用, 因此,我们是否可以认为,在line BBB处发生了引用传递?

先留着疑问,我们继续往下看。

观点2:值传递

继续看一段代码

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   } }

上述示例,输出结果为"a", 而不是"b"。

我们在line AAA处新创建了一个Object Foo并将其引用fooRef在line  EEE处传给了方法changeReference()的参数aRef, 该方法内部引用aRef在line  DDD处被重新赋值。如果是引用传递,那么引用aRef在line EEE处已经被指向了新的Object,  输出应该为"b"才对,事实上是怎样的呢?事实上输出了"b",也就是说changeReference()方法改变了传入引用所指对象的值。

观点1和观点2的输出结果多少会让人有些困惑,别急,我们继续往下看。

深入分析

为了详细分析这个问题,把上述两段代码合起来:

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         } }

下面来深入内部来详细分析一下引用和Object内部的变化。来看下面图示:

① Line AAA, 申明一个名叫fooRef,类型为Foo的引用,并见其分配给一个新的包含属性值为"f"的对象,该对象类型为Foo。

Foo fooRef = new Foo("a"); // line AAA

 Java方法传参时采用哪种传递

② Line DDD, 方法内部,申明了一个Foo类型的名为aRef的引用,且aRef被初始化为null。

void changeReference(Foo a);

Java方法传参时采用哪种传递

③ Line CCC, changeReference()方法被调用后,引用aRef被分配给fooRef指向的对象。

changeReference(fooRef);

Java方法传参时采用哪种传递

④ Line FFF, 申明一个名叫bRef,类型为Foo的引用,并见其分配给一个新的包含属性值为"b"的对象,该对象类型为Foo。

Foo bRef = new Foo("b");

 Java方法传参时采用哪种传递

⑤ Line EEE, 将引用aRef重新分配给了包含属性"b"的对象。此处注意,并非将fooRef重新分配,而是aRef。

aRef = bRef;

 Java方法传参时采用哪种传递

⑥ Line CCC, 调用方法modifyReference(Foo  cRef)后,新建了一个引用cRef并将之分配到包含该属性"f"的对象上,该对象同时被两个引用fooRef和cRef指向着。

modifyReference(fooRef);

Java方法传参时采用哪种传递

⑦ Line DDD,  cRef.setAttribute("c");将会改变cRef引用指向的包含属性"f"的对象,而该对象同时被引用fooRef指向着。

cRef.setAttribute("c");

 Java方法传参时采用哪种传递

此时引用fooRef指向的对象内部属性值"f"也被重新设置为"c"。

Java内部方法传参不是引用传递,而是引用本身的"值"的传递,归根结底还是值传递。将一个对象的引用fooRef传给方法的形参newRef,将给该对象新增了一个引用,相当于多了一个alias。我们可以通过这个原引用fooRef,或这是方法参数里的新引用newRef去访问、操作原对象,也可以改变参数里的引用newRef本身的值,却无法改变原引用fooRef的值。

关于Java方法传参时采用哪种传递就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯