为什么说Java只有值传递?

先说一下。。以后可能不会怎么写Java相关的博客了,因为找到了字节跳动的实习工作,用Go/Python开发后端,所以这几天在抓紧时间学Go,在学Go的时候,了解到Go语言只有值传递,我突然就想起网上对Java是引用传递还是值传递有很多种说法,那么我的看法是:Java中同样只有值传递。理由且听我慢慢道来。

最简单的验证方法

其实要验证Java只有值传递有个非常简单的方法。首先我们要了解值传递和引用传递的区别是什么,其实“引用传递”这个词,在C++语言中听到得最多,在值传递中,实参是传入对象的一份拷贝,因此对参数的修改不会影响传入的对象。而在引用传递中,传递的是对象的一个别名,若创建引用后,原对象的地址发生改变,引用的对象依然不会改变,而这种机制目前我只在C++语言中听说过。(主要还是学过的编程语言太少)

这种机制甚至在C语言中都没有,那么C语言要通过函数去改变一个参数该怎么办呢?正确的做法是指针传递

void swap(int *a,int *b)
{
    int temp;
    temp = *a
    *a = *b;
    *b = temp;
}

指针传递可以改变传入的参数,那么它是引用传递吗?并不是,它只是传递了指针的值,而函数内部因为获取了指针的值,于是可以通过指针获取指向的对象,从而修改它。

指针传递在C++中也可以使用,而C++要实现同样的功能还可以使用引用传递:

void swap(int& a, int& b)
{
    int swap = a;
    a = b;
    b = swap;
}

那么这两种方法有什么区别呢?区别就是,在指针传递的方法中,改变指针的值,外部并不会变化。

例如下面这段代码(引用传递)输出10,引用发生改变:

而下面这段代码(指针传递)则还是输出5,因为外部的指针不会随之发生改变:

那么,通过这两个示例,我们就可以写出一段Java代码来验证一下Java中是引用传递还是值传递:

既然网上很多资料说,Java除了基本类型,都是引用传递,那么我们这里就写了一个类进行测试,在函数内部去修改了一下获取的参数。

你可以尝试运行这段代码,输出的结果仍是:TestObject{value=1},说明它和C++中的指针传递的机制是一样的。这也是为什么我认为Java中都是值传递的原因。

Java中不是没有指针吗?

Java只是对使用者封装了指针的概念,我们看下面这行代码:

Object o = new Object();

new Object()实际上是在堆上创建了一个对象,o这个局部变量,是分配在栈上的,一个八字节的引用(reference)类型,指向堆上的对象

所以可以认为o就是一个指针,具体的机制在深入理解java虚拟机第三版读书笔记03--1.3 对象的访问定位中也有提到,HotSpot使用的对象访问定位的方式是直接指针访问,栈上的reference数据存储的就是对象在堆中的地址。

因此我倾向于认为,Java的这种传参方式,类似于C++中的指针传递,并没有引用传递的概念,因此可以说,Java中只有值传递。

原创文章,作者:彭晨涛,如若转载,请注明出处:https://www.codetool.top/article/%e4%b8%ba%e4%bb%80%e4%b9%88%e8%af%b4java%e5%8f%aa%e6%9c%89%e5%80%bc%e4%bc%a0%e9%80%92%ef%bc%9f/

发表评论

电子邮件地址不会被公开。