为什么说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/

(0)
彭晨涛彭晨涛管理者
上一篇 2020年6月21日
下一篇 2022年4月13日

相关推荐

  • try-catch-finally字节码实例探究

    本文使用Idea的jclasslib插件查看字节码。本文全程自言自语,请勿自行代入。 概述 java是怎么处理try-catch-finally的? 我们在深入理解java虚拟机第…

    2020年4月8日
    0720
  • Java中的四种内部类

    我发现最近真是越来越没有东西写了。。。不可能天天学习新知识啊,最近在复习阶段了,复习的东西大多数是博客里写过的/(ㄒoㄒ)/ 复习Java基础的时候认真看了一下Java的内部类,这…

    Java 2020年5月23日
    0100
  • LinkedList源码分析

    相关文章:ArrayList源码分析 List家族一览: LinkedList简介 LinkedList的超类有List、Queue,说明它既有List的性质也有Queue的性质,…

    2019年12月2日
    080
  • Random在多线程下的问题以及ThreadLocalRandom类分析

    Ramdom在多线程环境下的问题 首先我们看一下Random类的nextInt源码: //产生[0,bound)的随机数 public int nextInt(int bound)…

    Java 2020年5月18日
    0540
  • 数据库理论之OLTP与OLAP

    OLTP OLTP 即联机事务处理,就是我们经常说的关系数据库,意即记录即时的增、删、改、查,就是我们经常应用的东西,主要供基层人员使用,进行一线业务操作,这是数据库的基础。 对于…

    项目/编程理论 2020年2月16日
    0310
  • 深入理解java虚拟机第三版读书笔记08

    以下是第七章 虚拟机类加载机制的内容 概述 Java虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,…

    2020年1月22日
    0300
  • ThreadLocal源码分析和相关理解

    总结 总结放前面防止太长不看: 每个线程都有一个threadLocals字段,是一个ThreadLocalMap的实例,所有的ThreadLocal代表的线程私有数据都存放在这里面…

    Java 2020年2月13日
    0210
  • 深入理解java虚拟机第三版读书笔记02

    以下是第二章 Java内存区域与内存溢出异常的内容 运行时数据区域 程序计数器 特点 程序计数器是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器。 程序计数器是…

    2020年1月5日
    0200
  • PriorityQueue源码分析

    总结 总结放前面防止太长不看: PriorityQueue是个最小堆,如果要改变排序顺序只能重写比较器传入构造方法。 内部元素要么实现Comparable接口,要么传入比较器进行比…

    Java 2020年2月10日
    0260
  • JDK8-Stream流库详解

    流提供了一种让我们可以在比集合更高的概念级别上指定计算的数据视图。通过使用流,我们可以说明想要完成什么任务,而不是说明如何去实现它。 流的创建 Collection.stream(…

    Java 2020年2月11日
    0150

发表回复

登录后才能评论