INTRODUCTION TO PROGRAMMING IN JAVA: PARAMETER PASSING

NOTE: This set of www pages is not the set of www pages for the curent version of COMP101. The pages are from a previous version that, at the request of students, I have kept on line.


CONTENTS

1. Call by value parameter passing
2. Call by reference value parameter passing
3. Command line arguments
4. Scope rules and lifetime of identifiers
 
4.1. Class scope
4.1. Block scope
4.1. Distinction between lifetime and visibility
4.1. Garbage collection



1. CALL BY VALUE PARAMETER PASSING

We have seem that methods may have formal parameters associated with them. These formal parameters get assigned copies of the actual parameters when the method is called. The parameter then acts as a local variable within the called method. Any changes made to the value of this variable last only for the lifetime of the method and do not affect the original value. This is called call by value parameter passing.

The effects of call by value parameter passing are illustrated in the short piece of application code given in Table 1. The output from this code is as follows:

localDataItem1 = 1
formalParameter = 1
formalParameter = 3
localDataItem1 = 1     
 

Thus, referring to the code presented in Table 1, we have a local data item localdataItem which is passed as the actual parameter to the doit method where it is output, changed and output again. However, this change does not effect the value of the data item in the calling method. This is because we are working with a copy of the data item and not the data item itself.

The disadvantage of the call by value parameter passing mechanism is that a copy is always made of the actual parameter to obtain the formal parameter.

// CALL BY VALUE APPLICATION
// Frans Coenen
// Thursday 15 July 1999
// The University of Liverpool, UK
      
class CallByValueApp {
	
    // --------------- METHODS ------------------

    /* MAIN METHOD: */
    
    public static void main(String[] args) {
        int localDataItem1 = 1;
        
	System.out.println("localDataItem1 = " + localDataItem1);
	doit(localDataItem1);
	System.out.println("localDataItem1 = " + localDataItem1);
	}
	
    /* DOIT */
    	
    public static void doit(int formalParameter1) {
        System.out.println("formalParameter1 = " + formalParameter1);
	formalParameter1=formalParameter1+2;
	System.out.println("formalParameter1 = " + formalParameter1);	
    }
}

Table 1: Call by value example




2. CALL BY REFERENCE VALUE PARAMETER PASSING

There are in fact two techniques used in Java for passing arguments. The second is called call by reference value and is used in relation to data items which are stored by reference such as an object or an array. Given an object identifier this "points" to a start address in memory where all the attributes and methods for that object are stored. Similarly given an array identifier this "points" to a start address in memory where all the elements of the array are stored. Thus if we wish to pass an array or object to a method we pass the identifier for that object which in fact is a reference to a start address and not the object itself. As a result any changes made to the values associated with the object/array will be carried out on the actual object and not a copy as in call by value.

 

This is illustrated by the code presented in Table 2 which will produce the following output:

localDataItem2 = {1,2}
formalParameter2 = {1,2}
formalParameter2 = {3,4}
localDataItem2 = {3,4}     

Note that the changes made here to the formal parameter are permanent. Programmers should be aware of this effect as it can lead to accidental changing of values associated with data items. The advantage offered by call by reference is that no copy is made of the data item, this gives significant efficiency advantages when dealing with large arrays or objects that have many attributes and methods associated with them.

Some more parameter passing examples are available using object references as arguments.

// CALL BY REFERENCE APPLICATION
// Frans Coenen
// Thursday 15 July 1999
// The University of Liverpool, UK
      
class CallByReferenceApp {
	
    // --------------- METHODS ------------------

    /* MAIN METHOD: */
    
    public static void main(String[] args) {
        int localDataItem2[] = {1,2};
        
	System.out.println("localDataItem2 = {" + localDataItem2[0] + 
		"," + localDataItem2[1] + "}");
	doit(localDataItem2);
	System.out.println("localDataItem2 = {" + localDataItem2[0] + 
		"," + localDataItem2[1] + "}");
	}
	
    /* DOIT */
    	
    public static void doit(int formalParameter2[]) {
    	System.out.println("formalParameter2 = {" + formalParameter2[0] 
		+ "," + formalParameter2[1] + "}");
	formalParameter2[0]=formalParameter2[0]+2;
	formalParameter2[1]=formalParameter2[1]+2;
	System.out.println("formalParameter2 = {" + formalParameter2[0] 
		+ "," + formalParameter2[1] + "}");	
    }
}

Table 2: Call by value example




3. COMMAND LINE ARGUMENTS


// HELLO WORLD PROGRAM 3
// Frans Coenen
// Thursday 15 July 1999
// The University of Liverpool, UK

class HelloWorld3 {

    /* ------ MAIN METHOD ------ */
    
    public static void main(String[] args) {
    	System.out.print("\nHello " + args[0] );
	System.out.println(" - Congratulations on writing " +
		"a more sophisticated Java program that " +
		"involves command line arguments!\n\n");
    }
}

Table 3: Yet another "Hello World" program

In all the examples studied so far we have included a formal parameter in our main method:

main(String[] args)

and so far we have accepted this as just something that we have to do to make our programs work. From our knowledge of arrays we can now see that this is an array of instances of the class Strings called args. We can pass a value to this argument (an actual parameter) from the keyboard when invoking a program. For example earlier on we wrote a "Hello World" program that allowed the user to input their name which was then echoed to the screen together with the phrase "Congratulations on writing your first Java program which features some input!". A revised version of this program is presented in Table 3.

We can invoke this program and pass an argument to it as follows:

java HelloWorld3 "Frans Coenen"   

The result will be:

Hello Frans Coenen - Congratulations on 
writing a more sophisticated Java 
program that involves command line 
arguments! 
 

The value Frans Coenen is called a command line argument. We can have as many of these as we like. For example we might revise our program so that the output statement reads:

System.out.print("\nHello " + args[0] + 
        args[1] + args [2]);

and then pass in three arguments:

java HelloWorld3 "Dr." "Frans" "Coenen"

Let us consider another example. The code presented in Table 4 takes any number of command line integer arguments, adds them up and returns the total. There is however a "snag" as command line arguments are always strings. We must therefore convert each input string into an integer. We can do this using the appropriate "parse" method in the appropriate wrapper class, the parseInt method found in the Integer wrapper class in this case.

Once compiled we can invoke the application class presented in table 4 as follows:

$ java AddUpApp 1 23 456 789 245 678 
0 34        

from which we would expect the reply:

Total = 2226    
// ADD UP APPLICATION
// Frans Coenen
// Wednesday 21 July 1999
// The University of Liverpool, UK
               
class AddUpApp {

    /* ------ MAIN ------ */

    public static void main(String[] args) {
    	final int ARGS_START_INDEX = 0;
    	int total = 0;
	
	for(int loopCounter=ARGS_START_INDEX;loopCounter < args.length;
				loopCounter++) {
	    total = total + Integer.parseInt(args[loopCounter]);
	    }
	System.out.println("Total = " + total + "\n");
	}
    }

Table 4: "Integer" command line arguments



4. SCOPE RULES AND LIFETIME OF IDENTIFIERS

Scope rules govern the lifetime and visibility of identifiers, i.e. the parts of a program where they can be used. The term visibility describes the parts of a programme where a data item my be used. The term lifetime describes the period of time during a programmes execution when a data item exists in the computer's primary storage. Visibility and lifetime are not necessarily the same thing. In Java there are two types of scope:

Class scope
Block scope

4.1 Class Scope

The members of a class have class scope. They are visible from anywhere in the class. Class (static) fields have a lifetime commensurate with the duration of the execution of a programme. Instance (non-static) fields have a lifetime commensurate with the existence of the associated instances of the class. Thus in the example application code given in Table 5 the identifier total is accessible from anywhere with in the class. The order in which members are declared is not significant (although it is considered good practice, for sound software engineering reasons of understandability and readability, to declare fields first, then constructors and then methods), for example the total field could have been declared at the end of the ScopeRuleExample class definition.

Remember that if a member of class is declared to be public it will is also be visible from outside the class. Similarly if a member of a class is declared to be protected it will be visible by any sub-classes that extend the current class.

 

Note that to use the code given in Table 5 we need an applications program of the form given in Table 6). The output would be as follows:

$ java ScopeRuleExampleApp
Total = 6, Average = 1.5

The exception to the above is where a field is overiden in a method contained within the class, i.e. where a local data item with the same name as a field is declared in a method. In this case the field is said to be occluded throughout the lifetime of the local data item, i.e. the field continues to exists but is temporerily not vissible.



4.2 Block Scope

Local data items have block scope. An identifier with block scope is only visible from the point within the block where it is declared to where the block ends. Remeber that a block is delimited by a pair of "braces" (i.e. an open brace '{' and a close brace '}'). A method is the simplest example of a block. Other examples include sequences of statements associated with loops or selection statements.

Thus, in Table 5, the local constant LOOP_START_VALUE and the local variable average are visible from line in the method (calculateTotal and outputTotal respectively) to the end of the method. Similarly in the "for" loop contained in the calculateTotal method, the loopCounter local data item only exits in the block associated with the "for" loop.

Identifiers in formal parameter lists are also regarded as having block scope, for example (in Table 5) the data item number in the outputTotal method exist from where it is declared to the end of the method.


// SCOPE RULES EXAMPLE
// Frans Coenen
// Wednesday 21 July 1999
// Revised Tuesday 3 December 2002
// The University of Liverpool, UK
               
class ScopeRuleExample {

    private int total = 0;
	
    /* ------ CALCULATE TOTAL ------ */

    public void calculateTotal(int number) {
    	final int LOOP_START_VALUE = 0;
	
        for(int loopCounter=LOOP_START_VALUE;loopCounter < number;
				loopCounter++) {
            total = total+loopCounter; 
            }
	}
                                  
/* ------ OUTPUT TOTAL ------ */

    public void outputTotal(int number) {
        float average = total/(float) number;
        System.out.println("Total = " + total + ", Average = " + 
				average + "\n");
        }
    }

Table 5: Scope rule illustration

// SCOPE RULES EXAMPLE APPLICATION
// Frans Coenen
// Wednesday 21 July 1999
// Revised Tuesday 3 December 2002
// The University of Liverpool, UK
               
class ScopeRuleExampleApp {

    /* ------ MAIN ------ */

    public static void main(String[] args) {
    
    	ScopeRuleExample newScopeRuleEx = new ScopeRuleExample();
	
	int number = 4;
	newScopeRuleEx.calculateTotal(number);
	newScopeRuleEx.outputTotal(number);
	}
    }

Table 6: Scope rule illustration application program


4.3 Distinction Between Lifetime and Visibility

The distinction between the lifetime and the visibility of a data item can best be illustrated by reconsidering the code presented in Table 5 (ScopeRuleExample). AS we have noted above the instance field, total, has class scope; i.e. it has a lifetime commensurate with the existence of an associated instance of the class ScopeRuleExample2, but is only visible from within the class. The total instance field is not visible outside of the class; although, provided that we have an instance of the class ScopeRuleExample, the field will still exist.

The distinction between the lifetime and the visibility of a data item can be further illustrated by considering the code presented in Table 7 (ScopeRuleExample2) which is a variation on the scopeRuleExample class definition presented in Table 5. Here the local data item total in the calculateTotal method has block scope; i.e. it has a lifetime and visibility from when it is declared to the end of block it is declared in. During this item's lifetime the instance field with the same name is not visible (although it still exists); we say that the instance field has been occluded.

 

Although the code in Table 7 serves to further demonstrate the distinction between visibility and lifetime it is clearly not a good idea (from a software engineering view point) to have local data items and fields that share the same name --- unless there is a good reason for this.

Given an appropriate application class (along the lines of that presented in Table 6) the output from the code presented in Table 7 will be:

$ java ScopeRuleExample2App
Total = 6, Average = 1.5
 
Total = 0, Average = 0.0

i.e. the total instance field never gets a value (other than its initialisation value) assigned to it.

// SCOPE RULES EXAMPLE
// Frans Coenen
// Wednesday 21 July 1999
// Revised Tuesday 3 December 2002
// The University of Liverpool, UK
               
class ScopeRuleExample2 {

    private int total = 0;
	
    /* ------ CALCULATE TOTAL ------ */

    public void calculateTotal(int number) {
        final int LOOP_START_VALUE = 0;
        int total = 0;
	
        for(int loopCounter=LOOP_START_VALUE;loopCounter < number;
			loopCounter++) 
            total = total+loopCounter;
	    
	System.out.println("Total = " + total + ", Average = " + 
			(total/(float) number) + "\n");    
        }
                                  
    /* ------ OUTPUT TOTAL ------ */

    public void outputTotal(int number) {
        float average = total/(float) number;
	
        System.out.println("Total = " + total + ", Average = " + 
			average + "\n");
        }
    }

Table 7: Scope rule illustration Example 2: distinction between visibility and lifetime


4.4 Garbage Collection

We have noted that the lifetime of an identifier is the period over which it exists in computer memory. When an identifier goes out of scope the amount of memory associated with storing the identified data item or object is no longer required and the JVM (Java Virtual Machine) will return the memory back to the heap for future use. If this did not happen we would run out of memory! (Remember that the heap is an area of memory set aside for the dynamic allocation of computer memory for data items and objects during run time.) The process of automatically returning memory to the heap when it is no longer required during program execution is referred to as garbage collection.

If desired we can force garbage collection using the gc() method found in the System class.




Created and maintained by Frans Coenen. Last updated 10 February 2015