前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >《Java从入门到失业》第四章:类和对象(4.4):方法参数及传递

《Java从入门到失业》第四章:类和对象(4.4):方法参数及传递

作者头像
用户7801119
发布2020-09-27 14:58:35
1.1K0
发布2020-09-27 14:58:35
举报
文章被收录于专栏:java从入门到失业

4.4方法参数及传递

       关于这个知识点,我想了很久该不该在这里阐述。因为这个知识点稍微有点晦涩,并且就算不了解也不影响用Java编写代码。不过笔者刚开始工作的时候,就是因为这块内容没有过多的关注,以至于相当于长一段时间对这块内容都模糊不清甚至误解。我相信你们都比我悟性高,因此决定还是先拿出来讨论。

       我们知道,一个方法一般由修饰符、返回值、方法名和参数列表构成。这里我们主要讨论方法的参数。看一个例子:

代码语言:javascript
复制
  // 构造方法  
    public Mahjong(int type, int number) {  
        this.type = type;  
        this.number = number;  
    }  

这是麻将类的构造方法,有2个参数。我们看到参数由参数类型和参数名构成。参数类型可以是任何类型(即基本数据类型、类类型)。参数名需要满足标识符规范,一般建议使用有含义的名称。因为方法将会作为API的一部分暴露给调用者阅读,不要因为参数名的晦涩难懂而影响可读性。

4.4.1形参和实参

       我们看一下构造一个麻将的代码:

代码语言:javascript
复制
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语言中,只有值调用一种方式,不管传递的是基本数据类型还是类类型。值调用因为传递的是内存的值,因此不管传递的是基本数据类型还是类类型,都不会改变实参内存中的值。我们先看一个基本数据类型的例子:

代码语言:javascript
复制
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的值,并没有发生变化。为什么呢?实际上这个执行的过程如下:

  1. 定义变量v,给v分配一块内存,内存中的值存放5
  2. 调用changeValue方法,分配一块内存给形参value,并将v的值拷贝到value的内存中
  3. 执行方法,将value内存中的值加4,变成9,但是v的内存存放仍然是5
  4. 方法结束,释放value内存

我们用一张图来解释:

我们再看一个传递类类型方法调用的代码:

我们先给美人类增加一个修改器方法:

代码语言:javascript
复制
public void setName(String name) {  
        this.name = name;  
    }  

然后,写一个changeName方法,并调用,代码如下:

代码语言:javascript
复制
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());// 结果输出 西施  
    }  
} 

前面我们说过值调用不会改变形参的值,但是这里好像把貂蝉的名字改成西施了,为啥呢?我们先分析下执行过程:

  1. 定义变量diaochan并构造一个美人对象赋值给它,给diaochan分配一块内存,同时在堆内存中分配空间存放美人对象。变量diaochan内存中的存放的是美人对象的地址,假设地址为0xA1
  2. 调用changeName方法,分配一块内存给形参player,并将diaochan的值拷贝到player的内存中,因此形参player的值也为0xA1,指向美人对象
  3. 执行changeName方法,调用形参player的修改器setName方法,实际上就是调用美人对象的setName方法,因此美人对象的名字变成“西施”。
  4. 方法结束,释放形参player内存,实参diaochan和美人对象的内存依然存在

我们也用一张图来演示:

我们看到自始至终,实参diaochan内存中的值一直没变,都是0xA1。因为美人对象的名字变了,因此有的网文甚至有的书籍说Java类类型是引用调用,笔者认为是属于错误的说法。因为看是否是值调用,根本是要看是否传递的是实参内存的值,Java中类类型的传递,也是传递的实参内存中的值,只不过这个值是一个对象的地址(即引用)。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-09-21 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 4.4方法参数及传递
    • 4.4.1形参和实参
      • 4.4.2值调用和引用调用
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档