Java核心技术第4章(5)

4.5 方法参数

    按值调用(call by value)表示方法接收的是调用者提供的值,而按引用调用(call by reference)表示方法接收的是调用者提供的变量地址.一个方法可以修改传递引用所对应的变量值,而不能修改传递值调用所对应的变量值.
    Java程序设计语言总是采用按值调用,也就是说,方法得到的是所有参数值的一个拷贝,特别是,方法不能修改传递给它的任何参数变量的内容.
    例如,考虑下面的调用:
double percent = 10;
harry.raiseSalary(percent);
    在方法调用后,percent的值还是10.
    下面再仔细地研究一下这种情况,假定一个方法试图将一个参数值增加至3倍:
public static void tripleValue(double x) 
{
    x = 3 * x;
}
    然后调用这个方法:
double percent = 10;
harry.raiseSalary(percent);
    无论怎样, 调用这个方法后,percent的值还是0.下面看一下具体的执行过程:
    1.x被初始化为percent值的一个拷贝
    2.x变为30,但是percent仍然是10
    3.这个方法结束后,参数变量x不再使用.
    方法参数共有两种类型:
    基本数据类型(数字,布尔值)
    对象引用

    一个方法不可能修改一个基本数据类型的参数.而对象引用作为参数就不同了,可以很容易地利用下面这个方法实现将一个Employee的薪金提高至3倍的操作:
public static void tripleSalary(Employee x)
{
    x.raiseSalary(300);
}
    当调用
harry = new Employee(...);
tripleSalary(harry);
    时,具体的执行过程为:
    1.x被初始化为harry值的拷贝,这里是一个对象的引用
    2.raiseSalary方法应用于这个对象引用.
    3.方法结束后,参数变量x不再使用,对象变量harry继续引用的薪金提高至3倍
    实现一个改变对象参数状态的方法并不是一件难事.理由很简单,方法得到的是对象引用的拷贝,对象引用及其他的拷贝同时引用同一个对象.
    C++提供了两种参数传递的方式:值传递和引用传递.有些程序员认为Java程序设计语言采用的是引用调用,实际上,这种理解是不对的.下面给出一个反例来详细地阐述一下这个问题.
    首先编写一个交换两个Employee对象的方法:
public static void swap(Employee x, Employee y)
{
    Employee temp = x;
    x = y;
    y = temp;
}
    如果Java程序设计语言对对象采用的是引用调用,那么这个方法就应该能够实现交换来那个数据的效果:
Employee a = new Employee("Alice", ...);
Employee b = new Employee("Bob", ...);
swap(a, b);
    但是,方法并没有改变存储在变量a和b中的对象引用.swap方法的参数x和y被初始化为两个对象引用的拷贝,这个方法交换的是这两个拷贝.
// x refer to Alice, y to Bob
Employee temp = x;
x = y;
y = temp;
// now x refers to Bob, y to Alice
    在方法结束时参数变量x和y被丢弃了.原来的变量a和b仍然引用这个方法调用之前引用的对象.
    这个过程说明:Java程序设计语言对对象采用的不是引用调用.实际上,对象引用进行的是值传递.
    刚看完这两个例子就晕了,既然可以改变对象参数的状态,为什么不能让对象参数指向新对象呢? 这篇文章讲的很赞,直接贴图了.

    下面总结一下Java程序设计语言中方法参数的使用情况:
    一个方法不能修改一个基本数据类型的参数(即数值型和布尔型)
    一个方法可以改变一个对象参数的状态
    一个方法不能让对象参数引用一个新的对象

    程序ParamTest.java给出了相应的演示:
public class ParamTest
{
    public static void main(String[] args)
    {
        /**
         * Test1: Methods can't modify numeric paramters
         */
        System.out.println("Testing tripleValue:");
        double percent = 10;
        System.out.println("Before: percent = " + percent);
        tripleValue(percent);
        System.out.println("After: percent = " + percent);


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


        /**
         * Test3: Methods can't attach new objects to object paramters
         */
        System.out.println("\nTesting swap:");
        Employee a = new Employee("Alice", 7000);
        Employee b = new Employee("Bob", 6000);
        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)
    {
        x = 3 * x;
        System.out.println("End of method: x = " + x);
    }
    public static void tripleSalary(Employee x)
    {
        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
{
    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;
    }
}
    结果如下所示:

    注释:C++有值引用和引用调用.引用参数标有&符号.例如,可以轻松地实现void tripleValue(double& x)方法或void swap(Employee& x, Employee& y)方法实现修改它们的引用参数的目的.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值