《Java从入门到失业》第四章:类和对象(4.4):方法参数及传递
4.4方法参数及传递
关于这个知识点,我想了很久该不该在这里阐述。因为这个知识点稍微有点晦涩,并且就算不了解也不影响用Java编写代码。不过笔者刚开始工作的时候,就是因为这块内容没有过多的关注,以至于相当于长一段时间对这块内容都模糊不清甚至误解。我相信你们都比我悟性高,因此决定还是先拿出来讨论。
我们知道,一个方法一般由修饰符、返回值、方法名和参数列表构成。这里我们主要讨论方法的参数。看一个例子:
// 构造方法
public Mahjong(int type, int number) {
this.type = type;
this.number = number;
}
这是麻将类的构造方法,有2个参数。我们看到参数由参数类型和参数名构成。参数类型可以是任何类型(即基本数据类型、类类型)。参数名需要满足标识符规范,一般建议使用有含义的名称。因为方法将会作为API的一部分暴露给调用者阅读,不要因为参数名的晦涩难懂而影响可读性。
4.4.1形参和实参
我们看一下构造一个麻将的代码:
int t= 1;
int n = 2;
Mahjong m = new Mahjong(t, n);
形参:上面麻将构造方法中的参数type、number,我们称之为形参,即形式参数。形参是定义方法的时候使用的参数,用来接收调用者传递的参数。方法在调用的时候,形参才会被分配内存空间,一旦方法调用完毕,形参的内存就会被释放。
实参:这段代码中,我们先定义2个参数t和n,然后把t和n传递给麻将类的构造方法,t和n我们称之为实参,即实际参数。实参是调用者传递给方法的参数,实参需要在调用之前赋值,即在方法调用之前就已经分配了内存空间,并且方法调用完毕之后内存不会释放。用一张图来示意:
4.4.2值调用和引用调用
从上一小节我们看到,当调用方法的时候传递的是基本数据类型时,实际上是把实参的内存中的值传递给形参,这种方法调用我们称之为“值调用”。
实际上,在程序语言中还有一种称作“引用调用”的方式,例如C++同时存在值调用和引用调用两种方式。引用调用是把实参内存地址传递给形参。注意和值调用的区别:
- 值调用传递的是实参“内存的值”
- 引用调用传递的是实参“内存的地址”
可能有的同学有点懵了,内存的值和内存的地址有什么区别?回忆一下我们在第一章介绍内存的时候用来作比喻的蜂巢,蜂巢的每一个格子就相当于内存,它们都有一个唯一的编号,这就是内存地址,而格子里存放的东西就是内存的值。只不过内存的地址和内存的值都是二进制,因此容易混淆。
事实上,在Java语言中,只有值调用一种方式,不管传递的是基本数据类型还是类类型。值调用因为传递的是内存的值,因此不管传递的是基本数据类型还是类类型,都不会改变实参内存中的值。我们先看一个基本数据类型的例子:
public class Method {
public static void changeValue(int value) {
value += 4;
} public static void main(String[] args) {
int v = 5;
changeValue(v);
System.out.println(v);// 输出结果是5,v的值没有改变
}
}
我们看到,定义int变量v,然后传递给changeValue方法,方法内部把形参的值加4,但是对于实参v的值,并没有发生变化。为什么呢?实际上这个执行的过程如下:
- 定义变量v,给v分配一块内存,内存中的值存放5
- 调用changeValue方法,分配一块内存给形参value,并将v的值拷贝到value的内存中
- 执行方法,将value内存中的值加4,变成9,但是v的内存存放仍然是5
- 方法结束,释放value内存
我们用一张图来解释:
我们再看一个传递类类型方法调用的代码:
我们先给美人类增加一个修改器方法:
public void setName(String name) {
this.name = name;
}
然后,写一个changeName方法,并调用,代码如下:
public class Method { public static void changeName(Player player) {
player.setName("西施");
} public static void main(String[] args) {
Player diaochan = new Player("貂蝉");
changeName(diaochan);
System.out.println(diaochan.getName());// 结果输出 西施
}
}
前面我们说过值调用不会改变形参的值,但是这里好像把貂蝉的名字改成西施了,为啥呢?我们先分析下执行过程:
- 定义变量diaochan并构造一个美人对象赋值给它,给diaochan分配一块内存,同时在堆内存中分配空间存放美人对象。变量diaochan内存中的存放的是美人对象的地址,假设地址为0xA1
- 调用changeName方法,分配一块内存给形参player,并将diaochan的值拷贝到player的内存中,因此形参player的值也为0xA1,指向美人对象
- 执行changeName方法,调用形参player的修改器setName方法,实际上就是调用美人对象的setName方法,因此美人对象的名字变成“西施”。
- 方法结束,释放形参player内存,实参diaochan和美人对象的内存依然存在
我们也用一张图来演示:
我们看到自始至终,实参diaochan内存中的值一直没变,都是0xA1。因为美人对象的名字变了,因此有的网文甚至有的书籍说Java类类型是引用调用,笔者认为是属于错误的说法。因为看是否是值调用,根本是要看是否传递的是实参内存的值,Java中类类型的传递,也是传递的实参内存中的值,只不过这个值是一个对象的地址(即引用)。
《Java从入门到失业》第四章:类和对象(4.4):方法参数及传递的更多相关文章
- Java学习日记基础篇(四)——类,对象之成员变量,成员方法,构造方法
面向对象(Object Oriented) 一.面向对象杂谈 面向对象(Object Oriented),我的翻译是以物体为目标的,就是说编程的时候是建立一个物体,然后对这个物体进行操作. Java语 ...
- 《Java入门第二季》第一章 类和对象
什么是类和对象 如何定义 Java 中的类 如何使用 Java 中的对象 Java中的成员变量和局部变量1.成员变量:在类中定义,描述构成对象的组件. 2.局部变量:在类的方法中,用于临时保存数据. ...
- 《Java从入门到失业》第二章:Java环境(四):IDE集成环境
2.4IDE集成环境 在掌握了编写.编译和运行Java程序的基本步骤以后,你肯定就在想,这太麻烦了,有没有更好的工具?当然有了,那就是IDE.IDE就是专业的集成开发环境(Integrated Dev ...
- 《Java从入门到失业》第一章:计算机基础知识(一):二进制和十六进制
0 前言 最近7年来的高强度工作和不规律的饮食作息,压得我有些喘不过气,身体也陆续报警.2018年下半年的一场病,让我意识到了这个问题的严重性,于是开始强制自己有规律饮食和作息,并辅以健身锻炼,不到2 ...
- 《Java从入门到失业》第二章:Java环境(一):Java SE安装
从这一章开始,终于我们可以开始正式进入Java世界了.前面我们提到过,Java分三个版本,我们这里只讨论Java SE. 2.1Java SE安装 所谓工欲善其事,必先利其器.第一步,我们当然是要下载 ...
- 《Java从入门到失业》第一章:计算机基础知识(三):程序语言简介
1.3程序语言简介 我们经常会听到一些名词:低级语言.高级语言.编译型.解释型.面向过程.面向对象等.这些到底是啥意思呢?在正式进入Java世界前,笔者也尝试简单的聊一聊这块东西. 1.3.1低级语言 ...
- 《Java从入门到失业》第二章:Java环境(三):Java命令行工具
2.3Java命令行工具 2.3.1编译运行 到了这里,是不是开始膨胀了,想写一段代码来秀一下?好吧,满足你!国际惯例,我们写一段HelloWorld.我们在某个目录下记事本,编写一段代码如下: 保存 ...
- 《Java从入门到失业》第二章:Java环境(二):JDK、JRE、JVM
2.2JDK.JRE.JVM 在JDK的安装目录中,我们发现有一个目录jre(其实如果是下一步下一步安装的,在和JDK安装目录同级目录下,还会有一个jre目录).初学Java的同学,有时候搞不清楚这3 ...
- 《Java从入门到失业》第一章:计算机基础知识(二):计算机组成及基本原理
1.2计算机组成及基本原理 1.2.1硬件组成 这里说的计算机主要指微型计算机,俗称电脑.一般我们见到的有台式机.笔记本等,另外智能手机.平板也算.有了一台计算机,我们就能做很多事情了,比如我在写这篇 ...
- java面向对象编程——第四章 类和对象
OO:面向对象 OOP:面向对象编程 OOA:面向对象分析 OOD:面向对象设计 结构化编程:从顶向下,将一个大问题分解成更小的任务,然后为每一个更小的任务编写一个过程.最后程序员会编写一个主过程来启 ...
随机推荐
- Hyperledger Fabric【区块链学习一】
Hyperledger Fabric 学习 什么是区块链 什么是区块链在我们没有接触的时候,只知道它是一个去中心化的存储方式.当我们发生交易,或者动作的时候我们会将记录通知给所有参与者共同维护,达到去 ...
- mysql join update
SELECT CONCAT('UPDATE free_for_demo_orders SET product_id=',product_id,',order_created_time=','&quo ...
- nova start 虚机的代码流程分析
nova start 虚机的代码流程分析,以ocata版本为分析基础1.nova api服务接受用户下发的 nova start启动虚机请求其对应的http restfull api接口为post / ...
- Mybatis—curd
Mybatis简介: MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为 ...
- 启用valgrind的MPI支持
TL;DR sudo apt install valgrind-mpi 内存泄漏和越界问题,是C/C++程序常见问题.有一些工具提供了检测内存泄漏的功能,如 valgrind 的 memchecker ...
- OMG,12 个精致的 Java 字符串操作小技巧,学它
字符串可以说是 Java 中最具有代表性的类了,似乎没有之一哈,这就好像直播界的李佳琪,脱口秀中的李诞,一等一的大哥地位.不得不承认,最近吐槽大会刷多了,脑子里全是那些段子,写文章都有点不由自主,真的 ...
- 使用BeetleX在Linux下部署.NET多站点服务
在windows下常用IIS来部署.NET的多站点服务,但在Linux下就没这么方便了:虽然可以使用一些代理服务器如nginx,jexus等来反代或部署应用,但nginx对.NET应用的 ...
- 据说是最好的记忆工具——Anki
http://www.ankichina.net/ .u1s1,确实挺好用,自建题库,全程自助. 可以插入文字.图片.音频,会安排合理的复习频率,可以随时同步,电脑手机版本全.
- Arbitrary-Oriented Object Detection with Circular Smooth Label(ECCV2020,旋转目标检测)
论文链接:https://arxiv.org/abs/2003.05597 code:https://github.com/Thinklab-SJTU/CSL_RetinaNet_Tensorflow ...
- Prometheus 与 国产 TDengine 的对比
通过对比,能加深对这两个系统的理解,方便后续架构选型时作出正确决定.他们的设计思路有很多值得借鉴的地方,虽然工作中需要用到这些知识的地方不多,但是了解他们的设计细节能极大满足我的好奇心. 1.场景和需 ...