NO.1 方法参数按“值”而非按“引用”方式传递 | Java敲黑板系列

本文深入探讨Java中方法参数的传递机制,重点讲解按值调用的概念,并通过案例分析基本类型和对象类型的参数传递区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

图1

基本概念

方法(也称函数)调用是程序设计语言一种最基本的功能。一个完整的方法声明一般包括了返回值、方法名称、方法参数三个基本要素,俗称“三朵金花”。今天我们主要来谈谈这金兰三姐妹中的幺妹——方法参数。

方法被调用其中有一个重要的过程,就是对三妹进行虚实结合,也称形参与实参相结合,平时三妹就是一个符号,发生方法调用时,调用方会把实际的参数传递给方法。传递的方式分为两种:按值调用与按引用调用

按值调用:表示方法接收的是调用者提供的值
按引用调用:表示方法接收的是调用者提供的变量地址

上述两者最大的区别在于,前者不能修改传递值所对应的变量值;后再可以修改传递引用所对应的变量值。是不是有点绕?没有关系,现在只需要记住上述两种方式几乎涵盖了所有编程语言中方法参数的传递方式。此外,最为重要的是:Java语言使用了按值调用的方法参数的传递方式

案例分析

以下案例主要是为了说明其思想,采用了伪代码形式。

案例1

public static changeCircle(Point center, int radius){
      center.setLocation(10,10);
      radius = 100;
      System.out.println("In changeCircle. center is: " + center + "; radius is : " + radius);
}

static void main(String[] args){
      Point pt = new Point(0,0);
      int r  = 5;
      changeCircle(pt, r);
      System.out.println("After changeCircle. center is: " + pt + "; radius is : " + r);
}

答案:
In changeCircle. center is : (10,10); radius is : 100
After changeCircle. center is: (10,10);radius is : 5

解析:
执行完成后 ,可以发现pt变量的值发生了变化,r变量的值没有发生变化。为什么?开始敲黑板:Java语言使用了按值调用的方法参数的传递方式。我们下面用这个原则来分别进行解释:

(1)首先分析变量r。首先变量r是“基本数据类型”,在进行虚实结合的时候,发生了以下的事情:

  • 方法changeCircle中的变量radius会用main方法的变量r的拷贝值进行初始化;
  • 此后,在方法changeCircle中的radius会被更新为100,但是此时的变量r不会发生任何改变;(因为是按值传递)
  • 方法changeCircle结束后radius变量不再有任何用处。详情下图。

图2

(2)然后,我们再来看看变量pt到底发生了什么。首先pt是一个对象参数;类比(1)中的分析,由于Java是通过传值的方式进行传递参数,为此发生方法调用时,变量pt会产生一个副本传递给center变量,由于两个对象变量是不同的对象,为此后续就互不影响。这样对吗?错!其实从程序输出中也可以看出,center变量的修改的确是影响了变量pt的值。这是为什么了?

敲黑板:在Java中,如果方法参数是对象类型,那么传递的是对象的引用的复件,而不是对象的复件。两者之间有巨大的差别:对象的引用其实就是对象变量所对应的地址,这就说明发生方法调用时,pt变量的地址通过传值的方式传递给了center变量的地址,让两个变量指向了同一个对象,center成为了pt的别名,为此所有对center变量成员变量的修改都会同样作用于pt身上。为此,我们看到了调用changeCircle后,pt的值发生了变化。同样的,我们分步骤看看到底发生了什么:

  • center被初始化为pt对象的引用,即两个变量的地址相同,都指向了同一个对象(也就是同一块内存区域)
  • 对center对象所有成员变量的进行修改。所有的修改结果都会反馈到pt对象上。因为两者是同一对象,只是名字不一样而已。
  • 方法调用结束后,center变量不再有用。但是所有的修改情况都反映在变量pt上了。详情见下图。

图3

案例2

public static swap(Point p1, Point p2){

      Point temp = p1;

      p1 = p2;

      p2 = temp;

      System.out.println("In swap. p1 is: " + p1 + "; p2 is : " + p2);

}


public static void main(String[] args){

      Point pt1 = new Poin(0,0);

      Point pt2 = new Point(10,10);

      swap(pt1, pt2);

      System.out.println("In main. pt1 is: " + pt1 + "; pt2 is : " + pt2);
}

这算是一个思考题吧,请老铁们想想该程序会输出什么?请在留言区写出你的答案,正确答案会在下篇文章中进行公布。

小结

敲黑板,画重点:

  1. Java语言中的方法参数使用了按值调用的方法。具体来讲,对于基本类型变量采用了值拷贝的方式;对于对象变量采用了对象引用拷贝的方式。
  2. 上述传递方式也不用死记硬背,记下下面的两个例子,就完全理解了。可以把方法调用时方法参数传递方式类比于Java中的赋值操作。
int  val = 5;
int  passVal = val;
//基本类型赋值操作后,val与passVal独立变化,互不影响;
//等同于基本类型的方法参数调用

Point pnt = new Point(5,5);
Point passPnt = pnt; 
//对象类型赋值操作后,两个变量指向了同一个对象。
//在调试器中可以看见两个对象的ID是相同的。
//其中一个变量的成员变化都会同样作用于另外的一个变量
//等同于对象类型的方法参数调用

转载自公众号:代码荣耀
图4

电动汽车数据集:2025年3K+记录 真实电动汽车数据:特斯拉、宝马、日产车型,含2025年电池规格和销售数据 关于数据集 电动汽车数据集 这个合成数据集包含许多品牌和年份的电动汽车和插电式车型的记录,捕捉技术规格、性能、定价、制造来源、销售和安全相关属性。每一行代表由vehicle_ID标识的唯一车辆列表。 关键特性 覆盖范围:全球制造商和车型组合,包括纯电动汽车和插电式混合动力汽车。 范围:电池化学成分、容量、续航里程、充电标准和速度、价格、产地、自主水平、排放、安全等级、销售和保修。 时间跨度:模型跨度多年(包括传统和即将推出的)。 数据质量说明: 某些行可能缺少某些字段(空白)。 几个分类字段包含不同的、特定于供应商的(例如,Charging_Type、Battery_Type)。 各列中的单位混合在一起;注意kWh、km、hr、USD、g/km和额定。 列 列类型描述示例 Vehicle_ID整数每个车辆记录的唯一标识符。1 制造商分类汽车品牌或OEM。特斯拉 型号类别特定型号名称/变体。型号Y 与记录关联的年份整数模型。2024 电池_类型分类使用的电池化学/技术。磷酸铁锂 Battery_Capacity_kWh浮充电池标称容量,单位为千瓦时。75.0 Range_km整数表示充满电后的行驶里程(公里)。505 充电类型主要充电接口或功能。CCS、NACS、CHAdeMO、DCFC、V2G、V2H、V2L Charge_Time_hr浮动充电的大致时间(小时),上下文因充电方法而异。7.5 价格_USD浮动参考车辆价格(美元).85000.00 颜色类别主要外观颜色或饰面。午夜黑 制造国_制造类别车辆制造/组装的国家。美国 Autonomous_Level浮点自动化能力级别(例如0-5),可能包括子级别的小
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值