Download Method invocation and parameter passing

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
School of Informatics, University of Edinburgh
Computer Science 1 Ah
CS1Ah Lecture Note 30
Method invocation and parameter
passing
In this lecture note we study how parameter values are passed to methods. At the point
where a method is invoked we have the actual parameters whose values are copied and
passed to the formal parameters of the method. The mechanism by which parameters
are passed to methods varies from one programming language to another and it is
sometimes very complex. One of the design goals for the Java programming language
was that it should be (relatively) easy to learn so Java has only one type of parameter
passing where other languages have three or more. Java has also chosen the simplest
kind of parameter passing, termed call-by-value.
Methods with and without parameters
Consider the following Java program to print messages in a frilly style. It has one
method which has no parameters printBanner() and one which has a single String
parameter, printFrilly().
class PrintFrilly {
static void printBanner() {
System.out.println("<<<<<<>>>>>>");
}
static void printFrilly(String s) {
System.out.println("<<<" + s + ">>>");
}
public static void main(String[] args) {
printBanner();
for (int i = 0 ; i < args.length ; i++) {
printFrilly(args[i]);
}
printBanner();
}
}
1
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
School of Informatics, University of Edinburgh
Computer Science 1 Ah
If we run this program with the command java PrintFrilly three little words
it produces an attractive display in which the words are encased in a lovely jewelled
box fashioned from the best quality angle bracket characters.
<<<<<<>>>>>>
<<<three>>>
<<<little>>>
<<<words>>>
<<<<<<>>>>>>
A method with no parameters, such as printBanner(), will do the same task every
time that it is invoked. Such methods are sometimes useful because they attach a
descriptive identifier to a block of code (the method body). Breaking a long block of
statements into a number of methods with clearly defined roles is a useful programming technique which clarifies the structure of a program.
The task executed by a method with parameters, such as printFrilly(), will
change every time that the values of the parameters change. In the above example
this method is invoked three times and performs a different task each time (a different
word is printed in the frilly style in each case).
30.1 Java calls by value
When a method with parameters is invoked in a Java program the actual parameter
expressions are evaluated in left-to-right order to give the values which are to be passed
to the method. The formal parameters are given these initial values and the method
body is executed. If the formal parameter variables are updated in the method body this
change is not reflected in the actual parameters which were used for this invocation.
This kind of parameter passing is known as call-by-value.
class CallByValue {
static void assignString(String st) {
st = "The string in the method";
}
public static void main(String[] args) {
String st = "The default initial string";
assignString(st);
System.out.println(st);
}
}
//
//
//
//
//
//
//
//
//
//
1
2
3
4
5
6
7
8
9
10
When this program is executed it prints The default initial string. The key to
understanding why this happens is to note that there are two variables named st
which are declared in this program. One is declared at line 6 and the other as the
parameter of the assignString() method at line 2. The st variable from line 6 belongs
only to the main() method and the st variable declared at line 2 belongs only to the
assignString() method. Neither method can alter the variable owned by the other.
2
School of Informatics, University of Edinburgh
Computer Science 1 Ah
As this program is executed it first initialises the String variable st in the body
of the main() method. This variable’s value is retreived from memory to be passed to
the assignString() method when it is invoked at line 7. This gives the initial value
for the formal parameter of the method but then this initial value is overwritten by
the string constant used in the assignment which is performed on line 3. The method
invocation then completes and the local variable of the method is no longer accessible,
nor the value which it held. When the println() method is invoked it is the default
initial string which is printed.
Method invocations build up a stack of activation records, one for each method
invocation. These store the values of the local variables of the method, and other
information such as the return address which identifies the statement in the program
where execution is to begin again when this method invocation returns. Below we show
how the contents of the stack of activation records changes as this program executes.
st The default initial string
⇓
(the assignString() method is invoked)
st The default initial string
st The default initial string
⇓
(the assignment to st is performed)
st The string in the method
st The default initial string
⇓
(the invocation of assignString() returns)
st The default initial string
30.2
Passing references by value
What if we would like to structure our program in such a way that we have methods
which update the state of our objects? This is possible even though the Java parameter
passing mechanism is call-by-value. When we pass an object reference by value we are
able to access and update any of its public fields.
The following program shows how such a structure could be put into a Java program. If we wish to have a String variable updated by a method invocation we place
the String variable inside a class definition as one of its public fields. In the following
program we use a nested class for this purpose. The definition of the StringRef class
appears in the body of the UseStringRef class. Classes can contain other classes just
as they can contain fields or methods. The use of nested classes is not essential for
passing updateable fields, we could instead have placed the definition of the StringRef
class in a file StringRef.java and this would have had just the same effect.
In this program there are two uses of StringRef variables called r. One is the
local variable of the main() method, declared at line 12. The other is the formal
parameter of the assignStringRef() method, introduced at line 7. Although these
are different variables they both store the same reference, so they are not just equal
(using equals()) they are identical (using ==). This means that when we dereference
them to refer to r.st at lines 8 and 15 we access the same String variable.
3
School of Informatics, University of Edinburgh
Computer Science 1 Ah
class UseStringRef {
static class StringRef {
public String st;
}
static void assignStringRef(StringRef r) {
r.st = "The string in the method";
}
public static void main(String[] args) {
StringRef r = new StringRef();
r.st = "The default initial string";
assignStringRef(r);
System.out.println(r.st);
}
}
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
When we execute this program it prints The string in the method. However, the
mode of parameter passing is still call-by-value. The variable which was passed as
a parameter was the StringRef r, whereas it was the String field r.st which was
updated.
Stephen Gilmore.
Javier Esparza, 2003/01/03 14:09:16.
4