【Java】引用传递?值传递?

打印 上一主题 下一主题

主题 939|帖子 939|积分 2817

引用传递和值传递,从上学那会儿就开始强调的概念,不管你是计算机相关专业还是自学Java,一定听过这么一句话:
方法调用参数如果是对象,那就是引用传递,如果是基本数据类型,就是值传递。
比如:function(Object o)就是引用传递,function(int i)就是值传递。这两个概念似乎很好理解,我们只需要记住对象和基本数据类型的区别就行了。但是,真的是这样吗?
有一段代码如下:
  1.     public static void main(String[] args) {
  2.         int i = 0;
  3.         System.out.println(i);
  4.         change(i);
  5.         System.out.println(i);
  6.     }
  7.     private static void change(int i) {
  8.         i = 1;
  9.     }
复制代码
输出结果比较好猜测,也应该都能答对:
  1. 0
  2. 0
复制代码
下一个问题,如果将int改成String呢?
  1.     public static void main(String[] args) {
  2.         String s = "0";
  3.         System.out.println(s);
  4.         change(s);
  5.         System.out.println(s);
  6.     }
  7.     private static void change(String s) {
  8.         s = "1";
  9.     }
复制代码
输出的结果如下:
  1. 0
  2. 0
复制代码
嗯?有疑问了吧?不是引用传递吗?我在方法里命名修改了s的值,为什么输出还是”0“呢?难度String作为Object有什么特殊性?
别急,继续看下一段代码:
  1.     public static void main(String[] args) {
  2.         Person p = new Person("0");
  3.         System.out.println(p);
  4.         change(p);
  5.         System.out.println(p);
  6.     }
  7.     private static void change(Person p) {
  8.         p = new Person("1");
  9.     }
  10.     static class Person{
  11.         String name;
  12.         public Person(String name) {
  13.             this.name = name;
  14.         }
  15.         @Override
  16.         public String toString() {
  17.             return "Person{" +
  18.                     "name='" + name + '\'' +
  19.                     '}';
  20.         }
  21.     }
复制代码
结果会输出什么?
  1. Person{name='0'}
  2. Person{name='0'}
复制代码
看来String和其他Object没什么不同,可是这样的结果好像不太符合我们对引用传递的认知啊。其实我感觉这两个概念没有必要区分,实质是一回事,都是将栈中引用复制了一份传递到方法中,无论在方法中如何对引用操作,都是操作的副本,只是对于基本数据类型来说,值存储在栈中,引用存储的就是值,而对象来说,引用中存储的是对象在堆中的内存地址,参数传递时生成的副本仍然指向了原来引用指向的对象,所以如果直接操作该对象是有效的。简单画个图方便理解:
[img]https://img2023.cnblogs.com/blog/3076343/202305/3076343-202305221340
05869-15804904.png[/img]
 如果对p的操作不是将该引用指向一个新的值,而是对p指向的对象进行操作,就能看到所谓引用传递的效果了例如:
  1.     public static void main(String[] args) {
  2.         Person p = new Person("0");
  3.         System.out.println(p);
  4.         change(p);
  5.         System.out.println(p);
  6.     }
  7.     private static void change(Person p) {
  8.         p.name = "1";
  9.     }
  10.     static class Person{
  11.         String name;
  12.         public Person(String name) {
  13.             this.name = name;
  14.         }
  15.         @Override
  16.         public String toString() {
  17.             return "Person{" +
  18.                     "name='" + name + '\'' +
  19.                     '}';
  20.         }
  21.     }
复制代码
此时,执行结果为:
  1. Person{name='0'}
  2. Person{name='1'}
复制代码
总结:
Java进行方法调用时参数传递是将栈中的引用复制了一份到该方法的工作区,如果引用指向了一个堆中的对象,那么副本也指向这个对象。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

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

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

反转基因福娃

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表