Java核心技术卷一 -第四章:方法参数

系列文章目录

Java核心技术卷一 -第一章:java“白皮书”的关键术语
Java核心技术卷一 -第三章:数据类型
Java核心技术卷一 -第三章:变量与常量
Java核心技术卷一 -第三章:运算符
Java核心技术卷一 -第三章:字符串
Java核心技术卷一 -第三章:输入与输出
Java核心技术卷一 -第三章:数组
Java核心技术卷一 -第四章:类之间的关系-依赖
Java核心技术卷一 -第四章:预定义类-LocalDate类小应用
Java核心技术卷一 -第四章:构造器
Java核心技术卷一 -第四章:null引用


前言

本人为java初学者,文章内容仅为个人学习总结分享,其中包含了大量Java核心技术卷一里面的文章内容以及一些网站文章内容,由于参考文章过多,在此并不一一列出,如有侵权,请联系删除。

一、回顾

首先回顾一下在程序设计语言中关于如何将参数传递给方法(或函数)的一些专业术语。按值调用(call by value)表示方法接收的是调用者提供的值。而按引用调用(call byreference)表示方法接收的是调用者提供的变量地址。方法可以修改按引用传递的变量的值,而不能修改按值传递的变量的值。“按……调用”(call by)是一个标准的计算机科学术语,用来描述各种程序设计语言(不只是Java)中方法参数的传递方式(事实上,以前还有按名调用(call by name),Algol程序设计语言是最古老的高级程序设计语言之一,它使用的就是这种参数传递方式。不过,这种传递方式已经成为历史)。

二、Java的选择

Java程序设计语言总是采用按值调用。也就是说,方法得到的是所有参数值的一个副本。具体来讲,方法不能修改传递给它的任何参数变量的内容。
例如,考虑下面的调用:

double percent =10;
harry.raiseSalary(percent);

不论这个方法具体如何实现,我们知道,在这个方法调用之后,percent的值还是10。
下面再仔细研究一下这种情况。假定一个方法试图将一个参数值增加至3倍:

public static void tripleValue(double x)//doesn't work
{
X=3*X;

然后调用这个方法:

double percent =10;
tripleValue(percent);

不过,这样并不能起作用。调用这个方法之后,percent的值还是10。下面看一下具体的执行
过程:
1.x初始化为percent值的一个副本(也就是10)。
2.×乘以3后等于30,但是percent仍然是10
(如图1所示)。
3.这个方法结束之后,参数变量×不再使用。
图(1)
在这里插入图片描述

三、Java中的两种类型参数

然而,Java中有两种类型的方法参数:

1:基本数据类型(数字、布尔值)。
2:对象引用。

你已经看到,一个方法不可能修改基本数据类型的参数、而对象引用作为参数就不同了,可以很容易地利用下面这个方法将一个员工资增至三倍:

public static void tripleSalary(Employee x)//works
{
x.raiseSalary(280);

当调用

harry new Employee(…);
tripleSalary(harry);

时,具体的执行过程为:

1.x初始化为harry值的一个副本,这里就是一个对象引用。
2.raiseSalary方法应用于这个对象引用。x和harry同时引用的那个Employee对象的工资提高了200%。
3.方法结束后,参数变量x不再使用。当然,对象变量harry继续引用那个工资增至3倍的员工对象(如图2所示)。

图(2):
在这里插入图片描述
可以看到,实现一个改变对象参数状态的方法是完全可以的。实际上也相当常见。理由很简单,方法得到的是对象引用的副本,原来的对象引用和这个副本都引用同一个对象。

四、反例说明

很多程序设计语言(特别是C+和Pascal)提供了两种参数传递的方式按值调用和按引用调用。有些程序员(甚至有些书的作者)认为程序设计通对对象采用的是按引用调用,实际上,这种理解是不对的。由于这种误解具有一定的普避性,所以很有必要给出用个反例来详细地说明一下这个问题。
首先,编写一个交换两个Employee对象的方法:

public static void swap(Employee x,Employee y)/doesn't work
{
Employee temp x;
x=y;
y = temp;
}

如果Java对对象采用的是按引用调用,那么这个方法就应该能够实现交换:

var a new Employee("Alice",…);
var b new Employee("Bob",…):
swap(a,b);
//does a now refer to Bob,b to Alice?

但是,这个方法并没有改变存储在变量a和b中的对象引用。swap方法的参数x和y被初
始化为两个对象引用的副本,这个方法交换的是这两个副本。

//x refers to Alice,y to Bob
Employee temp =x;
x=y;
y = temp;
//now x refers to Bob,y to Alice

最终,白费力气。在方法结束时参数变量x和y被丢弃了。原来的变量a和b仍然引用
这个方法调用之前所引用的对象(如图3所示)。
图(3):
在这里插入图片描述
这个过程说明:Java程序设计语言对对象采用的不是按引用调用,实际上,对象引用是按值传递的
下面总结一下在Java中对方法参数能做什么和不能做什么:

●方法不能修改基本数据类型的参数(即数值型或布尔型)。
●方法可以改变对象参数的状态。
●方法不能让一个对象参数引用一个新的对象。

五、例子代码说明

下面程序展示了以上所说的这几点。在这个程序中,首先试图将一个数值参数的值增至三倍、但没有成功:

Testing triplevalue:
Before: percent=10.0
End of method:x=30.0
After: percent=10.0

随后,成功地将一个员工的工资增至三倍:

Testing tripleSalary:
Before: salary=50000.0
End of method:salary=150000.0
After: salary=150000.0

方法结束之后,harry引用的对象状态发生了改变。这是因为这个方法可以通过对象引用的副本修改所引用对象的状态。
最后,程序演示了swap方法的失败效果:

Testing swap:
Before: a=Alice
Before: b=Bob
End of method: x=Bob
End of method: y=Alice
After: a=Alice
After: b=Bob

可以看出,参数变量×和y交换了,但是变量a和b没有受到影响。
程序代码:

package Package01;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.util.Comparator;
import java.util.TreeSet;

public class Test01 {
    public static void main(String[] args)
    {
        /*
         * Test 1: Methods can't modify numeric parameters
         */
        System.out.println("Testing tripleValue:");
        double percent = 10;
        System.out.println("Before: percent=" + percent);
        tripleValue(percent);
        System.out.println("After: percent=" + percent);

        /*
         * Test 2: Methods can change the state of object parameters
         */
        System.out.println("\nTesting tripleSalary:");
        Employee harry = new Employee("Harry", 50000);
        System.out.println("Before: salary=" + harry.getSalary());
        tripleSalary(harry);
        System.out.println("After: salary=" + harry.getSalary());

        /*
         * Test 3: Methods can't attach new objects to object parameters
         */
        System.out.println("\nTesting swap:");
        Employee a = new Employee("Alice", 70000);
        Employee b = new Employee("Bob", 60000);
        System.out.println("Before: a=" + a.getName());
        System.out.println("Before: b=" + b.getName());
        swap(a, b);
        System.out.println("After: a=" + a.getName());
        System.out.println("After: b=" + b.getName());
    }

    public static void tripleValue(double x) // doesn't work
    {
        x = 3 * x;
        System.out.println("End of method: x=" + x);
    }

    public static void tripleSalary(Employee x) // works
    {
        x.raiseSalary(200);
        System.out.println("End of method: salary=" + x.getSalary());
    }

    public static void swap(Employee x, Employee y)
    {
        Employee temp = x;
        x = y;
        y = temp;
        System.out.println("End of method: x=" + x.getName());
        System.out.println("End of method: y=" + y.getName());
    }
}

class Employee // simplified Employee class
{
    private String name;
    private double salary;

    public Employee(String n, double s)
    {
        name = n;
        salary = s;
    }

    public String getName()
    {
        return name;
    }

    public double getSalary()
    {
        return salary;
    }

    public void raiseSalary(double byPercent)
    {
        double raise = salary * byPercent / 100;
        salary += raise;
    }
}

结果:
在这里插入图片描述在这里插入图片描述

总结

以上就是本文的内容,记录了一些关于java“方法参数”的内容,本人也是刚开始接触java,不能保证总结内容的正确性,若是有错误的话,欢迎大家指出,谢谢!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luodiab

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值