为什么 Java 中只有值传递?

2023-11-02

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

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

形参&实参

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

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

值传递&引用传递

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

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

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

为什么 Java 只有值传递?

为什么说 Java 只有值传递呢? 通过 3 个例子来介绍。

案例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

解析:
引用数据类型参数1
看了这个案例觉得 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 方法的参数 person1person2 只是拷贝的实参 xiaoZhangxiaoLi 的地址。因此, person1person2 的互换只是拷贝的两个地址的互换罢了,并不会影响到实参 xiaoZhangxiaoLi
引用数据类型参数2

总结

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

  • 如果参数是基本类型的话,很简单,传递的就是基本类型的字面量值的拷贝,会创建副本。
  • 如果参数是引用类型,传递的就是实参所引用的对象在堆中地址值的拷贝,同样也会创建副本。

参考

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

随机推荐

  • 基于powerlevel10k的mac terminal,速度超快(无需oh-my-zsh)

    ZSH 安装 一般mac最新的系统都自带zsh命令 只需 chsh s bin zsh 切换到zsh命令环境 这个环境对bash命令兼容 如果你之前配置过bash的环境 可以在 zshrc里面添加 最好是配置完terminal的主题后加 因
  • 华为OD机试真题- 篮球比赛-2023年OD统一考试(B卷)

    题目描述 篮球 5V5 比赛中 每个球员拥有一个战斗力 每个队伍的所有球员战斗力之和为该队伍的总体战斗力 现有10个球员准备分为两队进行训练赛 教练希望2个队伍的战斗力差值能够尽可能的小 以达到最佳训练效果 给出10个球员的战斗力 如果你是
  • 嘿!不备案不要HTTPS!小程序请求任意网站黑科技来了!

    顶着被 封 的危险 我要偷偷告诉你一个目前还没 公布 的黑科技 方法原创研发 并在实际项目中得到了很好的使用体验 好 认真往下看 我将会告诉你一个非常好玩 实用 黑科技的技能 这将让你扩展到更多小程序开发思路 从而实现之前无法实现的功能 来
  • php查询对象是否有某个属性可用,JavaScript 判断对象中是否有某属性的常用方法...

    判断对象中是否有某属性的常见方式总结 不同的场景要使用不同的方式 一 点 或者方括号 通过点或者方括号可以获取对象的属性值 如果对象上不存在该属性 则会返回undefined 当然 这里的 不存在 指的是对象自身和原型链上都不存在 如果原型
  • 报错Failed to load config “prettier“ to extend from.两步解决方案

    解决方案 1 进入项目根目录 npm i eslint prettier eslint eslint config prettier save dev 原因 I just had this error I was manually inst
  • SQLITE源码剖析

    http www iteye com blogs subjects deepfuture
  • 走进首个通用无代码开发平台—iVX

    目录 1 iVX简介 首个 通用 无代码 开发平台 应用可移植特性 2 iVX三大属性 iVX的语言属性 iVX的云属性 云原生 iVX的工具属性 3 iVX两大能力 代码生成能力 图灵完备 的逻辑能力 4 iVX能开发哪些应用 webAp
  • 离散化算法

    文章目录 离散化模板 巩固练习 电影 区间和 金发姑娘和 N 头牛 粉刷栅栏 线段覆盖 逆序对 程序自动分析 基本介绍 离散化 把无限空间中有限的个体映射到有限的空间中去 以此提高算法的时空效率 通俗的说 离散化是在不改变数据相对大小的条件
  • Flutter开发:Flutter UI之弹窗系列

    import dart io import package flutter material dart import package flutter services dart import package flutter app demo
  • [764]tmux简介及使用教程

    tmux是一个开源工具 用于在一个终端窗口中运行多个终端会话 它可以减少过多的打开终端控制台 tmux的源码在 https github com tmux tmux 它的License是BSD Tmux 是一个终端复用器 terminal
  • 记录yolov5更改backbone为ShuffleBlock网络迁移训练出错问题以及解决方法

    前言 最近在学习yolov5 记录一些报错 1 张量不对 Sizes of tensors must match except in dimension 1 Expected size 16 but got size 8 for tenso
  • 雾化(使用w分量)

    11
  • 将一个按钮固定在右下角

    fix btn position fixed bottom 5rem right 2rem
  • xpath——4k解析图片

    需求 解析下载图片数据 http pic netbian com 4kyouxi import requests from lxml import etree import os if name main headers User Agen
  • 互联网背景下为什么会出现NoSQL?

    一 传统应用模式 ALL IN ONE 所有的东西都部署在一台机器上 包括站点 数据库 文件等等 现在阿里云的出现方便了很多 核心工作就是 前端传过来一些数据 然后业务逻辑层拼装 然后访问数据库 数据库返回数据 数据拼装成页面 最终返回到浏
  • Python做一个简单的名片管理系统

    项目介绍 如下图 本次项目主要完成新建名片 显示全部名片 查询对应名片并对对应名片完成相关操作 框架搭建 名片管理首先可以由main py以及tools py组成 main py主要完成主要功能 tools主要完成选择分支下的功能 由于每次
  • 面经-阿里电话面试

    又是一年面试季节 闲来无事看看市面上都在找那些技术 查缺补漏弥补不足 当然如果能够找到不错的去处也是好的 说来惭愧 第一次接到阿里电话时正在外边跟同事吃饭 环境实在是不允许 冒昧的给推迟到第二天了 第二次 是第二天的下午开会中 由于手机静音
  • VLC相关参数中文说明!

    用法 vlc 选项 流 您可以在命令行中指定多个流 它们将被加入播放列表队列 指定的首个项目将被首先播放 选项样式 选项 用于设置程序执行期间的全局选项 选项 单字母版本的全局 选项 选项 一个仅在流之前应用的选项 且将覆盖先前的设置 流
  • 探索Java中的反射机制:解析类的信息与执行动态操作

    探索Java中的反射机制 解析类的信息与执行动态操作 引言 在Java编程领域中 反射机制是一项强大的工具 它使得我们能够在运行时动态地获取 使用类的信息 甚至可以对类进行修改 通过反射 我们可以在编译时未知类的情况下 通过获取类的构造方法
  • 为什么 Java 中只有值传递?

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