为什么Java中只有值传递?

您所在的位置:网站首页 java参数传递只存在值传递 为什么Java中只有值传递?

为什么Java中只有值传递?

2023-11-28 00:33| 来源: 网络整理| 查看: 265

1、必知概念:

实参:方法被调用时传入的实际值。形参:在定义方法时括号内定义的参数列表即为形参,它用来接收方法调用时传入的实参。值传递:当方法被调用时,实参通过形参将其副本传入方法内,接下来对形参的操作就是在对实参副本的操作,并不会影响实参本身。引用传递:当方法被调用时,实参的地址值通过形参将其传入方法内,所以对形参的改变就会映射到实参上。

    注意:值传递与引用传递的区别并不在于被传递参数的类型,也就是说,并不是传入的参数是基本数据类型就是值传递,同理,并不是传入的参数是引用类型就是引用传递。

2、Java中只有值传递的原因:

当形参为基本数据类型时: public class Test { public static void main(String[] args) { int num = 9; System.out.println("修改前的实参为:" + num); change(num); System.out.println("修改后的实参为:" + num); } private static void change(int temp) { System.out.println("传入的形参为:" + temp); temp++; System.out.println("修改后的形参为:" + temp); } }

    可以看出,这个过程虽然改变了形参,但是并没有改变实参的值,所以说是一次值传递过程。接下来就按照Java内存区域进行进一步分析:

    当程序启动时,首先执行main方法,此时就会在本地方法栈中创建一个关于main方法的栈帧进行压栈,栈帧中包含局部变量表(目前仅有num)及其他信息,因为在main方法中调用了change方法,所以要创建一个关于change方法的栈帧再次压栈,如下图所示,

    小结:修改的值是main中传入的num副本值,所以并不会修改num本身。

当形参为引用类型时: public class TestUser { public static void main(String[] args) { Person person = new Person(10, "一诺"); System.out.println("修改前的实参为:" + person); change(person); System.out.println("修改后的实参为:" + person); } private static void change(Person p) { p.setAge(100); p.setName("Cat"); } } public class Person { private int age; private String name; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Person(int age, String name) { this.age = age; this.name = name; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } }

    Amazing,为什么Person的属性发生了改变,不是值传递吗?不是不改变实参值吗?那么我们就通过Java内存区域来进一步分析:

    可以看出,传递的参数并不是Person对象的具体值,而是它的地址值,所以实参、形参指向的是堆内存中的同一个Person对象,这样我们对形参的修改就会体现在实参上。

    这样理解是没问题,但是我又想了一下,这样通过对象的地址值改变对象属性,这不是引用传递吗?不是说Java中只有值传递吗?带着这个疑问,我又反复看了好多次值传递、引用传递的概念,值传递每次传递的都是实参的副本啊,那要是顺着这条线想下去,那么change中p的值就是person地址值(0x11)的副本值呗,这样就可以解释了上述这个过程是值传递的过程了(不知道这样理解对不对,不对的话还请大家指正~)。

当形参为String等不可变类(Integer等包装类)时: public class TestString { public static void main(String[] args) { String str = new String("孙行者"); System.out.println("字符串修改前:" + str); change(str); System.out.println("字符串修改后:" + str); } private static void change(String str) { str = "行者孙"; } }

    ???为什么又和第二种情况不一样???String不是也是引用类型吗?怎么会出现这种情况呢?带着充满问号的脑袋,接着来按照Java内存区域进一步分析吧:

    可以看出,确实是将实参的副本传入给方法内,但是在change方法中做了一个 str = "行者孙" 的操作,因为String是不可变类,它一旦初始化就不可以再更改值了,因此这个操作是重新实例化了一个String对象,str也由 0x11 变为了 0x10,而0x11所指向的值没有改变,所以自然main方法中的str值不会变啦~

参考:

Java中到底是传递值还是传递引用(Java方法调用参数传递)_哔哩哔哩_bilibili为什么大家都说Java中只有值传递?_烟雨星空的博客-CSDN博客_为什么java只有值传递

总结:

    站在巨人的肩膀上才能看的更远,很庆幸能在网上找到前辈们写的文章来解答我的疑惑,同时也希望自己总结的文章能够帮助到别人。而对于这个本文分享的问题,之前我也很不理解为什么Java中只有值传递,但是在了解完Java内存区域后再看这些就很好理解了,在这篇文章我也没有很详细的介绍这部分内容,所以还是推荐对此问题有疑惑的朋友先去了解一下Java内存区域。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3