Java核心思想学习笔记001(Method Parameters)

原创 2006年05月24日 13:22:00

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 that is passed by reference but not in one that is passed by value. These "call by . . . " terms are standard computer science terminology that describe the behavior of method parameters in various programming languages, not just Java. (In fact, 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, the method gets a copy of all parameter values. In particular, the method cannot modify the contents of any parameter variables that are passed to it.

For example, consider the following call:

double percent = 10;

No matter how the method is implemented, we know that after the method call, the value of percent is still 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;

However, this does not work. After the method call, the value of percent is still 10. Here is what happens:

  1. x is initialized with a copy of the value of percent (that is, 10).

  2. x is tripled—it is now 30. But percent is still 10 (see Figure 4-6).

    Figure 4-6. Modifying a numeric parameter has no lasting effect

  3. 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

When you call

harry = new Employee(. . .);

then the following happens:

  1. x is initialized with a copy of the value of harry, that is, an object reference.

  2. 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%.

  3. 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).

    Figure 4-7. Modifying an object parameter has a lasting effect

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 methods for parameter passing: call by value and call by reference. Some programmers (and unfortunately even some book authors) claim that the Java programming language uses call by reference for objects. However, that is false. Because 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.

Figure 4-8. Swapping object parameters has no lasting effect

This discussion 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 the Java programming language:

  • A method cannot modify a parameter of 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 Example 4-4 demonstrates these facts. The program first tries to triple a 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++ 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.

Example 4-4
 1. public class ParamTest
 2. {
 3.    public static void main(String[] args)
 4.    {
 5.       /*
 6.          Test 1: Methods can't modify numeric parameters
 7.       */
 8.       System.out.println("Testing tripleValue:");
 9.       double percent = 10;
10.       System.out.println("Before: percent=" + percent);
11.       tripleValue(percent);
12.       System.out.println("After: percent=" + percent);
14.       /*
15.          Test 2: Methods can change the state of object
16.          parameters
17.       */
18.       System.out.println("/nTesting tripleSalary:");
19.       Employee harry = new Employee("Harry", 50000);
20.       System.out.println("Before: salary=" + harry.getSalary());
21.       tripleSalary(harry);
22.       System.out.println("After: salary=" + harry.getSalary());
24.       /*
25.          Test 3: Methods can't attach new objects to
26.          object parameters
27.       */
28.       System.out.println("/nTesting swap:");
29.       Employee a = new Employee("Alice", 70000);
30.       Employee b = new Employee("Bob", 60000);
31.       System.out.println("Before: a=" + a.getName());
32.       System.out.println("Before: b=" + b.getName());
33.       swap(a, b);
34.       System.out.println("After: a=" + a.getName());
35.       System.out.println("After: b=" + b.getName());
36.    }
38.    public static void tripleValue(double x) // doesn't work
39.    {
40.       x = 3 * x;
41.       System.out.println("End of method: x=" + x);
42.    }
44.    public static void tripleSalary(Employee x) // works
45.    {
46.       x.raiseSalary(200);
47.       System.out.println("End of method: salary="
48.          + x.getSalary());
49.    }
51.    public static void swap(Employee x, Employee y)
52.    {
53.       Employee temp = x;
54.       x = y;
55.       y = temp;
56.       System.out.println("End of method: x=" + x.getName());
57.       System.out.println("End of method: y=" + y.getName());
58.    }
59. }
61. class Employee // simplified Employee class
62. {
63.    public Employee(String n, double s)
64.    {
65.       name = n;
66.       salary = s;
67.    }
69.    public String getName()
70.    {
71.       return name;
72.    }
74.    public double getSalary()
75.    {
76.       return salary;
77.    }
79.    public void raiseSalary(double byPercent)
80.    {
81.       double raise = salary * byPercent / 100;
82.       salary += raise;
83.    }
85.    private String name;
86.    private double salary;
87. }


知己海内存 2016-11-29 23:28 @RequestMapping映射 1.@RequestMapping 映射请求注解 lSpringMVC使用@RequestMappi...
  • u011277123
  • u011277123
  • 2016年11月30日 09:23
  • 352


用junit对java代码进行单元测试时需要注意的问题。 1、用@Test注解的方法必须没有返回值,返回值类型无:void 2、用@Test注解的方法必须没有入参。 比如以下错误代码示例: p...
  • suyu_yuan
  • suyu_yuan
  • 2016年06月16日 17:59
  • 6165

数字格式化 把“1”格式化为“001”或“001”转换为1

//数字格式化 int k = 1; DecimalFormat mFormat = new DecimalFormat("000");//确定格式,把1转换为001 String s =...
  • Dr_abandon
  • Dr_abandon
  • 2016年09月10日 09:35
  • 2214


第一章 多线程 多线程和多进程之间的区别:   本质区别在于每个进程有他自己的变量的完备集,线程则共享相同的数据,这个听起来似乎有些危险,事实上也的确如此,你将会在本章后面的内容中看到这个问题,尽...
  • cxming007
  • cxming007
  • 2014年06月04日 18:38
  • 2283

spring cloud-Feign使用中遇到的问题总结

问题一: 在前面的示例中,我们讲过 @RequestMapping(value = "/user/{id}", method = RequestMethod.GET) @GetMapping("/us...
  • liuchuanhong1
  • liuchuanhong1
  • 2017年01月25日 11:25
  • 12286


一、介绍 泛型的概念代表了对类型的抽象(C++开发人员熟知的模板)。它是一个非常强大的概念,它允许开发抽象算法和数据结构,并提供实体类型以供后续操作。在早期的Java版本中并未出现泛型,泛型是在Ja...
  • zyhlwzy
  • zyhlwzy
  • 2018年01月10日 18:32
  • 108


Window -> Preferences -> Java -> Compiler。 选中Store information about method parameters (usable via ...
  • fm0517
  • fm0517
  • 2016年10月22日 17:46
  • 601

JUnit测试报错:java.lang.Exception: Method deleteDoc should have no parameters

一、问题描述 使用JUnit测试方法,一运行就提示错误: java.lang.Exception: Method deleteDoc should have no paramete...
  • u011781521
  • u011781521
  • 2017年08月25日 10:15
  • 879

001 - java字符串总结

  • xwc_shuck
  • xwc_shuck
  • 2017年12月23日 19:16
  • 16

spring cloud 学习笔记-消费服务

spring cloud 服务消费者
  • zzp448561636
  • zzp448561636
  • 2017年04月22日 19:18
  • 1948
您举报文章:Java核心思想学习笔记001(Method Parameters)