为什么 Java 中只有值传递?

2023-11-05

开始之前,我们先来搞懂下面这两个概念:

  • 形参&实参
  • 值传递&引用传递

形参&实参

方法的定义可能会用到 参数(有参的方法),参数在程序语言中分为:

  • 实参(实际参数) :用于传递给函数/方法的参数,必须有确定的值。
  • 形参(形式参数) :用于定义函数/方法,接收实参,不需要有确定的值。
String hello = "Hello!";
// hello 为实参
sayHello(hello);
// str 为形参
void sayHello(String str) {
    System.out.println(str);
}

值传递&引用传递

程序设计语言将实参传递给方法(或函数)的方式分为两种:

  • 值传递 :方法接收的是实参值的拷贝,会创建副本。
  • 引用传递 :方法接收的直接是实参所引用的对象在堆中的地址,不会创建副本,对形参的修改将影响到实参。

很多程序设计语言(比如 C++、 Pascal )提供了两种参数传递的方式,不过,在 Java 中只有值传递。

为什么 Java 只有值传递?

案例1:传递基本类型参数

public static void main(String[] args) {
    int num1 = 10;
    int num2 = 20;
    swap(num1, num2);
    System.out.println("num1 = " + num1);
    System.out.println("num2 = " + num2);
}

public static void swap(int a, int b) {
    int temp = a;
    a = b;
    b = temp;
    System.out.println("a = " + a);
    System.out.println("b = " + b);
}

输出:

a = 20
b = 10
num1 = 10
num2 = 20

解析:
在 swap() 方法中,a、b 的值进行交换,并不会影响到 num1、num2。因为,a、b 的值,只是从 num1、num2 的复制过来的。也就是说,a、b 相当于 num1、num2 的副本,副本的内容无论怎么修改,都不会影响到原件本身。

通过上面例子,我们已经知道了一个方法不能修改一个基本数据类型的参数,而对象引用作为参数就不一样,请看案例2。

案例2:传递引用类型参数1

	public static void main(String[] args) {
      int[] arr = { 1, 2, 3, 4, 5 };
      System.out.println(arr[0]);
      change(arr);
      System.out.println(arr[0]);
	}

	public static void change(int[] array) {
      // 将数组的第一个元素变为0
      array[0] = 0;
	}

输出:

1
0

看了这个案例很多人肯定觉得 Java 对引用类型的参数采用的是引用传递。

实际上,并不是的,这里传递的还是值,不过,这个值是实参的地址罢了!

也就是说 change 方法的参数拷贝的是 arr (实参)的地址,因此,它和 arr 指向的是同一个数组对象。这也就说明了为什么方法内部对形参的修改会影响到实参。

为了更强有力地反驳 Java 对引用类型的参数采用的不是引用传递,我们再来看下面这个案例!

案例3 :传递引用类型参数2

public class Person {
    private String name;
   // 省略构造函数、Getter&Setter方法
}

public static void main(String[] args) {
    Person xiaoZhang = new Person("小张");
    Person xiaoLi = new Person("小李");
    swap(xiaoZhang, xiaoLi);
    System.out.println("xiaoZhang:" + xiaoZhang.getName());
    System.out.println("xiaoLi:" + xiaoLi.getName());
}

public static void swap(Person person1, Person person2) {
    Person temp = person1;
    person1 = person2;
    person2 = temp;
    System.out.println("person1:" + person1.getName());
    System.out.println("person2:" + person2.getName());
}

输出:

person1:小李
person2:小张
xiaoZhang:小张
xiaoLi:小李

解析:

怎么回事???两个引用类型的形参互换并没有影响实参啊!

swap 方法的参数 person1 和 person2 只是拷贝的实参 xiaoZhang 和 xiaoLi 的地址。因此, person1 和 person2 的互换只是拷贝的两个地址的互换罢了,并不会影响到实参 xiaoZhang 和 xiaoLi 。

总结

Java 中将实参传递给方法(或函数)的方式是 值传递 :

  • 如果参数是基本类型的话,很简单,传递的就是基本类型的字面量值的拷贝,会创建副本。
  • 如果参数是引用类型,传递的就是实参所引用的对象在堆中地址值拷贝,同样也会创建副本
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 Java 中只有值传递? 的相关文章

随机推荐

  • 自定义动态数据源

    文章目录 准备 业务流程分析 代码实现 网页上切换数据源 准备 mysql spring boot 配置依赖 配置文件 数据源配置 spring datasource type com alibaba druid pool DruidDat
  • UnityVR--小程序3--金色的子弹2

    子弹需要一个打击目标 目标具备一定的生命值 HP 当生命值将为0时 目标被击落并消失 1 前篇的AXButton cs脚本不需要修改 2 子弹的程序Bullet cs中 OnTriggerEnter Collider other 函数修改为
  • 肖战

    肖战是中国内地男演员 歌手 主持人 毕业于中央戏剧学院表演系 他曾出演过多部影视剧 包括 花千骨 武媚娘传奇 和 长安十二时辰 此外 他还是一位多才多艺的歌手 曾发行过多张个人音乐专辑
  • 苹果开发平台常用网址链接

    苹果开发者中心 https developer apple com cn 苹果开发者中心 企业类型 https developer apple com cn programs enterprise 注册账号 https developer
  • react+antd实现Table拖拽调整列宽

    注意 列需要传入 width 并且配合下面的css样式才能显示拖拽手势 import React useEffect useState from react import Table from antd import Resizable f
  • PE半透明屏是怎么制造的?工艺、材料、应用

    PE半透明屏是一种新型的屏幕材料 具有半透明的特点 它由聚乙烯 PE 材料制成 具有良好的透明度和柔韧性 PE半透明屏广泛应用于建筑 广告 展览等领域 具有很高的市场潜力 PE半透明屏的特点之一是其半透明性 它可以在一定程度上透过光线 使得
  • 相关性分析热力图(Python&Matlab代码实现)

    目录 1 热力图 1 1 简介 1 2 语法 2 算例1 Python代码实现 2 1 算例 2 2 Python代码 2 3 运行结果 3 算例2 Python代码实现 4 算例3 Python代码实现 4 1 算例 4 2 Python
  • 小电容通高频大电容通低频的理解

    本文参考为什么电容通高频阻低频 记录下个人理解并总结 1 电容的作用是通高频阻低频 高频的时候电容总是还没充满电 负半周期便到来 所以电流始终存在 低频的时候信号交流电负半周还没到来 电容已充满电便发生断路 2 理论上电容越大 能通越高的高
  • 简单解释同步、异步、阻塞、非阻塞、中断、轮询、多线程,协程这几个概念(代码未验证,仅参考)

    科普 同步和异步的区别 同步和异步是指程序执行的方式 其中同步指程序按顺序执行 每个任务必须等待前面的任务执行完成后才能执行 而异步则指程序可以在执行一个任务时同时执行另一个任务 不需要等待前一个任务执行完毕 同步 Synchronous
  • supervisor源码分析

    Supervisor分析 1 运行原理概述 Supervisor生成主进程并将主进程变成守护进程 supervisor依次生成配置文件中的工作进程 然后依次监控工作进程的工作状态 并且主进程负责与supervisorctl客户端通信 实现主
  • c语言中求三个整数中的最大值和最小值,编程用指针实现输入三个整数,求其中的最大值...

    公告 为响应国家净网行动 部分内容已经删除 感谢读者理解 话题 编程用指针实现输入三个整数 求其中的最大值回答 include stdio h int getmax int p int n int i max p max p p 0 for
  • C++ 多线程 学习笔记

    线程睡眠很稳定 但无线程睡眠不稳定 线程调用类方法 有参数时调用方法 当参数为引用时 detach分离线程 分离线程与主线程同时进行 join会使主线程挂起 执行join进来的进程 detach必须让主线程在还住运行的情况下调用 换句话说就
  • harbor数据库迁移

    harbor数据库迁移 相同版本间迁移 一 数据导出 旧harbor机 1 进入数据库容器 root localhost docker exec u root it d53efe26b3da bin bash 2 导出registry数据库
  • KafkaConsumer-Kafka从入门到精通(十)

    上篇文章说了 消息压缩可以看分情况进行 判断下服务器cpu空闲还是io空闲较多 如果cpu空闲较多 则考虑消息积压 反之则不考虑 还有消费者组 consumer group 对于同一个group 只会发送一条消息进入一个实例 位移提交在0
  • php中mail,php中mail()函数和SMTP工作原理及实际

    php中mail 函数和SMTP工作原理及实际 发表于2019 05 24 12 36 次阅读 来源网络整理 作者session 摘要 php中mail 函数和SMTP工作原理及实际 php中mail 函数和SMTP工作原理及实际 一个发送
  • C++利用zxing识别二维码

    C 利用zxing识别二维码 下载编译 配置使用 Win10 x64 VS2015 VS2019 下载编译 1 下载zxing包 并解压 下载地址 https github com glassechidna zxing cpp build文
  • linux:TCP(传输控制协议)1、客户端和服务器连接并通信客户端,向服务器发送数据2、实现回传。服务器收到客户端的数据之后,将数据返传给客户端

    注意 服务器中的ip 192 168 31 122 和端口号port 6666 客户端中必须一致 编译 客户端 gcc tcp client c o client 服务器 gcc tcp server c o server 运行 客户端 c
  • GAN的图像修复:多样化补全

    点击上方 机器学习与生成对抗网络 关注 星标 获取有趣 好玩的前沿干货 2019 cvpr Pluralistic Image Completion https arxiv xilesou top pdf 1903 04227 pdf ht
  • 使用IO流对文件进行读取功能

    对于文件的读取可以用字符流也可以用字节流 下面整理了一份利用字节读流对本地文件进行读取 1 实现思路 第一步 选择文件 实例化一个文件File 在File的构造里放上你要读取的文件路径 文件路径的斜杠需要用转义符进行处理 如果文件在项目的根
  • 为什么 Java 中只有值传递?

    开始之前 我们先来搞懂下面这两个概念 形参 实参 值传递 引用传递 形参 实参 方法的定义可能会用到 参数 有参的方法 参数在程序语言中分为 实参 实际参数 用于传递给函数 方法的参数 必须有确定的值 形参 形式参数 用于定义函数 方法 接