当前位置: 首页 > news >正文

Java——详解形参实参方法的重载

文章目录

    • 一、实参和形参的关系
    • 二、方法的重载

一、实参和形参的关系

1.首先我们需要知道什么是形参什么是实参。
例如:

public int add(int a,int b)
{
return a+b;
}
//这里的a和b就是形参
//add(2,3)2和3就是实参,在调用时传给形参a和b

注意:在Java中,实参的值永远都是拷贝到形参中,形参和实参本质是两个实体
2.交换两个整型变量

public class TestMethod {public static void main(String[] args) {int a = 10;int b = 20;swap(a, b);System.out.println("main: a = " + a + " b = " + b);}public static void swap(int x, int y) {int tmp = x;x = y;y = tmp;System.out.println("swap: x = " + x + " y = " + y);}
}// 运行结果
//swap: x = 20 y = 10
//main: a = 10 b = 20

为什么会出现这样的情况呢?明明swap方法里面x和y已经交换了值,主方法里面的a和b却没有交换。
原因解释:

1.栈帧隔离:每次调用 invokestatic / invokevirtual 指令,JVM 都会在线程栈上为被调方法创建一个新的 Stack Frame。
局部变量表位于该帧内部,仅当前帧可见。
调用者的局部变量表与被调者的局部变量表物理隔离。
2.实参 → 形参 的复制过程:把调用者栈帧操作数栈顶上的 实参值复制一份将这份副本按顺序存入被调方法栈帧的局部变量,进入被调方法的字节码执行后,所有对形参的读写都只在当前帧的这些槽位进行,与调用者帧毫无关联。

Java 的所有参数传递都是“值传递”——实参把值复制一份给形参;方法里对形参重新赋值,只是改了这份副本,所以实参永远不变。
3.解决办法:传引用类型参数 (例如数组来解决这个问题)

public class TestMethod {public static void main(String[] args) {int[] arr = {10, 20};swap(arr);System.out.println("arr[0] = " + arr[0] + " arr[1] = " + arr[1]);}public static void swap(int[] arr) {int tmp = arr[0];arr[0] = arr[1];arr[1] = tmp;}
}// 运行结果
//arr[0] = 20 arr[1] = 10

接下来聊聊为什么能成功的原因
在此之前,我们先了解一下JVM的内存分布
在这里插入图片描述

程序计数器 (PC Register): 只是一个很小的空间, 保存下一条执行的指令的地址
虚拟机栈(JVM Stack): 与方法调用相关的一些信息,每个方法在执行时,都会先创建一个栈帧,栈帧中包含有:局部变量表、操作数栈、动态链接、返回地址以及其他的一些信息,保存的都是与方法执行时相关的一些信息。 比如:局部变量。当方法运行结束后,栈帧就被销毁了,即栈帧中保存的数据也被销毁了。
本地方法栈(Native Method Stack): 本地方法栈与虚拟机栈的作用类似. 只不过保存的内容是Native方法的局部变量. 在有些版本的 JVM 实现中(例如HotSpot), 本地方法栈和虚拟机栈是一起的
堆(Heap): JVM所管理的最大内存区域. 使用 new 创建的对象都是在堆上保存 (例如 new int[]{1, 2, 3} ),堆是随着程序开始运行时而创建,随着程序的退出而销毁,堆中的数据只要还有在使用,就不会被销毁。
方法区(Method Area): 用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据. 方法编译出的的字节码就是保存在这个区域

基本数据类型创建的变量,称为基本变量,该变量空间中直接存放的是其所对应的值;
引用数据类型创建的变量,一般称为对象的引用,其空间中存储的是对象所在空间的地址。就像这样
在这里插入图片描述
引用变量并不直接存储对象本身,可以简单理解成存储的是对象在堆中空间的起始地址。通过该地址,引用变量便可以去操作对象。
引用数据类型可以正确交换的原因:

交换的是堆对象的“内部状态”,而非形参变量本身。
方法里拿到的是对象引用的副本,但两个副本指向同一块堆内存。
通过该引用去修改对象的字段(或数组元素),所有持有同一引用的代码都会看到变化。因此,交换的是对象内部的数据,而不是交换形参变量里的引用值。

二、方法的重载

什么是方法重载:指在同一个类中,方法名相同,但参数列表不同(个数、类型或顺序不同)的一组方法。编译器根据调用时传入的实参列表,静态绑定(编译期)到最匹配的那个重载版本。

例如:

public class TestMethod {public static void main(String[] args) {add(1, 2);                // 调用add(int, int)add(1.5, 2.5);            // 调用add(double, double)add(1.5, 2.5, 3.5);       // 调用add(double, double, double)}public static int add(int x, int y) {return x + y;}public static double add(double x, double y) {return x + y;}public static double add(double x, double y, double z) {return x + y + z;}
}

1. 方法名必须相同
2. 参数列表必须不同(参数的个数不同、参数的类型不同、类型的次序必须不同)
3. 与返回值类型是否相同无关

注意:两个方法如果仅仅只是因为返回值类型不同,是不能构成重载的

##三、 方法签名

为什么可以定义相同方法名的方法呢,要如何区分这些方法呢?接下来便让我们的主角登场。
方法签名即:经过编译器编译修改过之后方法最终的名字。具体方式:方法全路径名+参数列表+返回值类型,构成方法完整的名字。
查看方法签名的方法:

  1. 先对工程进行编译生成.class字节码文件
  2. 在控制台中进入到要查看的.class所在的目录
  3. 输入:javap -v 字节码文件名字即可
    在这里插入图片描述

可以看到即使方法名相同,但签名不同。

http://www.dtcms.com/a/320273.html

相关文章:

  • 《C语言》函数练习题--3
  • (易视宝)易视TV is-E4-G-全志A20芯片-安卓4-烧写卡刷工具及教程
  • Docker国内可用镜像列表(长期免费)
  • 三重移相的TPS双有源桥(DAB)变换器【simulink仿真模型】
  • python见缝插针小游戏源码。(可复制)
  • 【tips】css模仿矢量图透明背景
  • 目前常用于视频会议的视频编码上行/下行带宽对比
  • mysql_mcp_server_pro源码部署及启动报错新手指南:让智能体长出手来直接获取到最底层的数据
  • AI应用案例全景分析:从理论到实践
  • dmctlcvt工具介绍数据文件路径变化后如何拉起数据库
  • 基于 FreeMarker 实现 SQL 模板动态生成的完整指南
  • 移动端项目框架推荐
  • Effective C++ 条款27: 尽量用const、enum、inline替换 #define
  • restTemplate禁用url编码
  • 安装mkdocs
  • Python从入门到精通——第六章 字典与集合
  • 「日拱一码」046 分支定界算法
  • Airflow 入门案例教程
  • 前端性能优化:从请求到资源的精细调控
  • 【第9话:感知算法基础1】深度学习神经网络模型基础知识概念入门简介
  • 批量获取亚马逊商品SKU商品规格调用流程
  • 【实时Linux实战系列】基于实时Linux的高频交易系统构建
  • Python 常用内置高阶函数
  • RabbitMQ面试精讲 Day 15:RabbitMQ故障转移与数据恢复
  • C++ min循环超超超详细指南
  • WFP DNS 域名解析
  • 深入理解C++模板进阶:非类型参数、特化与分离编译
  • Linux节点创建API与路径对应关系
  • AI日报0807 | GPT-5或今晚1点来袭:四大版本全曝光
  • 什么是 TDengine IDMP?