4.5. Method Parameters
Let us review the computer science terms that describe how parameters can be passed to a method (or a function) in a programming language. The term call by value(值调用) means that the method gets just the value that the caller provides(方法获得调用者的变量值). In contrast, call by reference(引用调用) means that the method gets the location of the variable that the caller provides(方法获得调用者的变量地址). Thus, a method can modify the value stored in a variable passed by reference but not in one passed by value. These "call by . . ." terms are standard computer science terminology describing the behavior of method parameters in various programming languages, not just Java. (There is also a call by name that is mainly of historical interest, being employed in the Algol programming language, one of the oldest high-level languages.)
The Java programming language always uses call by value. That means that the method gets a copy of all parameter values. In particular, the method cannot modify the contents of any parameter variables passed to it.
For example, consider the following call:

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

No matter how the method is implemented, we know that after the method call, the value of percent is still 10(无论raiseSalary如何实现,调用该方法后,percent的值仍是10).
Let us look a little more closely at this situation. Suppose a method tried to triple the value of a method parameter:

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

Let's call this method:

double percent = 10;
tripleValue(percent);

However, this does not work. After the method call, the value of percent is still 10(调用tripleValue方法后,percent的值仍是10).
Here is what happens:

  • x is initialized with a copy of the value of percent (that is, 10).
  • x is tripled—it is now 30. But percent is still 10 (see Figure 4.6).
  • The method ends, and the parameter variable x is no longer in use.

There are, however, two kinds of method parameters(方法的参数有两种):

  • Primitive types (numbers, boolean values)
  • Object references

You have seen that it is impossible for a method to change a primitive type parameter(一个方法不可能改变原始类型的参数值). The situation is different for object parameters(这与对象参数不同). You can easily implement a method that triples the salary of an employee:

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

When you call

harry = new Employee(. . .);
tripleSalary(harry);

then the following happens:

  • x is initialized with a copy of the value of harry, that is, an object reference.
  • The raiseSalary method is applied to that object reference. The Employee object to which both x and harry refer gets its salary raised by 200 percent.
  • The method ends, and the parameter variable x is no longer in use. Of course, the object variable harry continues to refer to the object whose salary was tripled (see Figure 4.7).

As you have seen, it is easily possible—and in fact very common—to implement methods that change the state of an object parameter. The reason is simple. The method gets a copy of the object reference, and both the original and the copy refer to the same object(方法取得对象引用的一份拷贝,原始引用和拷贝引用都指向同一个对象).
Many programming languages (in particular, C++ and Pascal) have two mechanisms for parameter passing: call by value and call by reference. Some programmers (and unfortunately even some book authors) claim that Java uses call by reference for objects. That is false. As this is such a common misunderstanding, it is worth examining a counterexample in detail.
Let's try to write a method that swaps two employee objects:

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

If the Java programming language used call by reference for objects, this method would work:

Employee a = new Employee("Alice", . . .);
Employee b = new Employee("Bob", . . .);
swap(a, b);
// does a now refer to Bob, b to Alice?

However, the method does not actually change the object references that are stored in the variables a and b. The x and y parameters of the swap method are initialized with copies of these references. The method then proceeds to swap these copies.

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

But ultimately, this is a wasted effort. When the method ends, the parameter variables x and y are abandoned. The original variables a and b still refer to the same objects as they did before the method call (see Figure 4.8).

This demonstrates that the Java programming language does not use call by reference for objects. Instead, object references are passed by value(对象的引用通过值传递).
Here is a summary of what you can and cannot do with method parameters in Java:

  • A method cannot modify a parameter of a primitive type (that is, numbers or boolean values).
  • A method can change the state of an object parameter.
  • A method cannot make an object parameter refer to a new object.

The program in Listing 4.4 demonstrates these facts. The program first tries to triple the value of a number parameter and does not succeed:

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

It then successfully triples the salary of an employee:

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

After the method, the state of the object to which harry refers has changed. This is possible because the method modified the state through a copy of the object reference.
Finally, the program demonstrates the failure of the swap method:

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

As you can see, the parameter variables x and y are swapped, but the variables a and b are not affected.


C++ Note
C++ has both call by value and call by reference. You tag reference parameters with &. For example, you can easily implement methods void tripleValue(double& x) or void swap(Employee& x, Employee& y) that modify their reference parameters.


Listing 4.4. ParamTest/ParamTest.java

 public class ParamTest
{
public static void main(String[] args)
{
// TODO: 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); // TODO: 2 Methods can change the state of object parameters
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()); // TODO: 3 Methods can't attach new object to object parameters
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 = x * 3;
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;
}
}

Core Java Volume I — 4.5. Method Parameters的更多相关文章

  1. Core Java Volume I — 1.2. The Java "White Paper" Buzzwords

    1.2. The Java "White Paper" BuzzwordsThe authors of Java have written an influential White ...

  2. Core Java Volume I — 3.10. Arrays

    3.10. ArraysAn array is a data structure that stores a collection of values of the same type. You ac ...

  3. Core Java Volume I — 5.1. Classes, Superclasses, and Subclasses

    5.1. Classes, Superclasses, and SubclassesLet's return to the Employee class that we discussed in th ...

  4. Core Java Volume I — 4.7. Packages

    4.7. PackagesJava allows you to group classes in a collection called a package. Packages are conveni ...

  5. Core Java Volume I — 4.6. Object Construction

    4.6. Object ConstructionYou have seen how to write simple constructors that define the initial state ...

  6. Core Java Volume I — 4.4. Static Fields and Methods

    4.4. Static Fields and MethodsIn all sample programs that you have seen, the main method is tagged w ...

  7. Core Java Volume I — 3.1. A Simple Java Program

    Let’s look more closely at one of the simplest Java programs you can have—one that simply prints a m ...

  8. Core Java Volume I — 3.8. Control Flow

    3.8. Control FlowJava, like any programming language, supports both conditional statements and loops ...

  9. Core Java Volume I — 3.6. Strings

    3.6. StringsConceptually, Java strings are sequences of Unicode characters(Java的字符串是一个Unicode序列). Fo ...

随机推荐

  1. php solr 查询

    $options = array( 'hostname' => 'localhost', 'port' => 8080, 'path' => 'solr/test'); $clien ...

  2. ASP.NET-遇到的错误汇总

    错误:“未在本地计算机上注册“Microsoft.Jet.OLEDB.4.0”提供程序.” 在win7 64未上,读取Excel中的数据时报的错误, 解决方法:在生成"配置管理器中" ...

  3. POJ 3206 最小生成树

    DESCRIPTION:T_T 在下是读不懂题意的.但是捏.现在知道是求把所有的点(是字母的点)连起来的最小的权值.即最小生成树.因为求最小生成树是不计较源点是哪个的.所以可以把A和S看成一样的.首先 ...

  4. HandleErrorAttribute 特性使用

    public class EwHandleErrorAttribute : HandleErrorAttribute { public override void OnException(Except ...

  5. 基于百度定位及天气获取的DEMO

    demo基于百度定位APIv4.0版.新浪天气(不用查询城市代码). 需求: 1.button实现触发定位监听和天气捕获 2.两个textview 分别显示详细地址.天气. 界面很简陋,侧重功能实现. ...

  6. Unity优化之减少Drawcall

    简单来说,Drawcall就是屏幕渲染一次所需要的开销,为了较少消耗,提高性能,一般有以下几种方法. 一: 批处理 1.动态批处理 如果动态物体共用着相同的材质,那么Unity会自动对这些物体进行批处 ...

  7. python建立pip.ini

    pip 是python的包管理器工具,类似linux的apt-get.yum包管理器,主要是用来进行安装python库, pip默认从官方源pypi.python.org下载数据,国内速度相对比较慢, ...

  8. CGAffineTransformMakeTranslation和CGAffineTransformTranslate

    分类: ios基础2013-01-06 22:05 15513人阅读 评论(2) 收藏 举报 1.CGAffineTransformMakeTranslation每次都是以最初位置的中心点为起始参照 ...

  9. GCD的多线程实现方式,线程和定时器混合使用

    GCD (Grand Central Dispatch) 性能更好,追求性能的话 1.创建一个队列 //GCD的使用 //创建一个队列 dispatch_queue_t queue = dispatc ...

  10. Unix/Linux获取进程的详细信息

    Linux的进程的信息都记录在/proc/<pid>/下面,其实常用的ps.top命令也是从这里读取信息的.常用的信息有: cmd(命令).cmdline(完整的命令行参数).envrio ...