Methods: Communicating with Objects
We communicate with objects using methods. Methods are executable code within each object, for which an interface has been established. Sometimes the interface is only for the object itself. Other times it is an interface accessible by other objects. This chapter discusses that topic in detail.
3.5 Passing a Value and Passing a Reference
The effect of passing arguments to a method differs depending on whether
you are passing a value of primitive type (such as 5 or true) or a value of
reference type (such as “Hello” or game1). When an argument of primiPassing a primitive value tive type is passed to a method, a copy of the argument is passed to the formal parameter. For example, consider the PrimitiveCall class shown
in Figure 3.7. Note that we have an int variable k, which initially stores
the value 5, and a method myMethod(), which takes an int parameter n.
In this case, when we invoke myMethod(k), k’s value (5) is copied into n
and stored there during the method.
One implication of passing a copy of a primitive value to a method is
that the original value of k in main() cannot be altered from inside the
method. Thus, the output generated by PrimitiveCall would be
Note that in main(), k’s value is printed both before and after
myMethod() is called, but that its value remains unaffected even though
n’s value is changed within the method. This is because myMethod()
contains just a copy of k’s value, not k itself. Any changes to the copy
within myMethod() leave k unaltered (See Fig. 3.8).
In contrast to this, when an argument of a reference type is passed to a
method, a copy of the reference to the object itself is assigned to the parameter. For example, in the case of a String parameter or a OneRowNim
parameter, the method would be given a reference to the object–that is,
the address of the object. The object itself is not passed, because it would
be too inefficient to copy the entire object with all its data and methods.
However, because the object’s reference gives the object’s location in memory, the method will have access to the object and can make changes to the
original object from within the method.
Figure 3.8: Tracing the state
of variables k and n in
PrimitiveCall (a) Just before calling myMethod(k) in
main. (b) Just before executing
the body of myMethod(). (c)
Just after executing the body of
myMethod(). (d) After flow of
control returns to main().
For example, consider the ReferenceCall class (Fig. 3.9). In this
case, myMethod() takes a parameter g of type OneRowNim. Because
a OneRowNim instance is an object, g is a reference variable. So when
myMethod(game) is invoked in main(), a reference to game is passed
to myMethod(). Note that in myMethod(), we use takeSticks(3) to
change the number of sticks of g from 10 to 7 and that this change persists
even after the method returns control to main(). The reason is that during the method’s execution, both game and g refer to the exact same object
(see Fig. 3.10). The output generated by ReferenceCall would be
This illustrates that when passing a reference variable to a method, it is
possible for the method to change the state of the object associated with
Figure 3.10: Tracing the
state of OneRowNim object in
ReferenceCall (a) Just before
calling myMethod(game). (b)
Just before executing the body of
myMethod(). (c) Just after executing the body of myMethod().
(d) After flow of control returns
the reference variable. In subsequent chapters we will see ways to make
use of this feature of reference parameters.