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

相关推荐

  • Java自动装箱缓存机制

    尝试运行这段代码: 相似的两段代码,得到的结果却完全不相同。 首先要知道在java中==比较的是对象的引用,从直觉出发,无论是integer1、integer2还是integer3…

    Java 2019年12月5日
    0130
  • 深入理解java虚拟机第三版读书笔记04

    以下是第三章 垃圾收集器与内存分配策略的内容 概述 程序计数器、虚拟机栈、本地方法栈是线程独有的,栈帧更是随方法结束而消亡,不需要垃圾回收。而堆和方法区则需要经过垃圾回收的设计 对…

    2020年1月8日
    0270
  • NIO网络编程之Selector介绍

    Selector 要实现异步IO要通过Selector,甚至我们可以通过一个线程管理多个Channel的读写,这是NIO相较BIO的优越之处之一。 Channel可以注册到一个Se…

    Java 2020年2月7日
    0730
  • ConcurrentHashMap源码分析

    ConcurrentHashMap的源码比较难读,特别是JDK8中几乎对其进行了重写,设计思想非常优秀,代码量也是非常多,不过我这里算是总结了一些相对重要的部分,仅供参考。 线程安…

    2020年2月13日
    0160
  • AQS及其应用ReentrantLock源码分析

    AQS原理 概述 全称是 AbstractQueuedSynchronizer(抽象同步队列),是阻塞式锁和相关的同步器工具的框架。 特点:+ 用 state 属性来表示资源的状态…

    2020年2月4日
    0110
  • 对象的输入输出-Java序列化机制

    对象序列化和反序列化,在Java中体现为两种字节流: ObjectInputStream、ObjectOutputStream 序列化的概念 指堆内存中的java对象数据,通过某种…

    Java 2019年12月21日
    0150
  • Java基础查缺补漏05

    继续我的复习刷题 可以有和类名同名的函数 题目: JAVA中,下列语句哪一个正确() A. class中的constructor不可省略B. constructor必须与class…

    Java 2020年5月29日
    0140
  • PriorityQueue源码分析

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

    Java 2020年2月10日
    0240
  • Java线程池详解

    线程池就是享元模式和生产者消费者模式的应用 动手实现线程池 步骤1:自定义拒绝策略接口 @FunctionalInterface // 拒绝策略 interface RejectP…

    2020年2月3日
    0300
  • HashMap源码分析

    HashMap是java中非常常见的一个数据结构,在这篇文章里,我依然以Map中的操作为导向来循序渐进研究HashMap中的源码,阅读这篇文章需要的前置知识有: 弱平衡的二叉查找树…

    Java 2020年2月12日
    0220

发表回复

登录后才能评论