Tuesday, June 17, 2008

Parameter Passing


Objects communicate with each other by sending messages. Sending a message basically means invoking one of the methods from the published contract of other object. Most of the methods will involve passing arguments back and forth between objects.

A method, in C/C++ or Java, can have only one return type, but the signature of method can have a number of arguments in it. For example, the following method declaration is valid:

public String getName( List myList, int count ) {

...
...
}

The above declaration says that the getName method accepts two parameters and returns a String. There is no syntactically legal construct that allows us to return two String objects.

C/C++ developers use a typical coding practice. The return from a method will always be an int. A return of zero indicates successful execution of the method whereas a non-zero return value indicates some error in method execution. This error code is then passed to another api to get the complete error report. A value that needs to be returned from the method is accepted as input argument itself which is subsequently modified in the method. A typical C/C++ api signature is as follows which clearly mentions input and output parameters.

/**
* This function will return all the views,
* for a given Item.
*/
extern C_API int ITEM_list_all_view_revs(

obj_o item, /** < (I) Tag of the item */
int* count, /** < (O) Number of views attached to the above Item */
obj_o** views /**< (OF) count objects of views for the Item */ );


This is where we have to be careful while passing arguments to ITEM_list_all_view_revs api. The obj_o is an input which will be read by the method to list the views. This will be pass by value. The int* count and obj_o** views will be mutated by the method. These have to be pass by reference.

Is it the same when we invoke methods in Java? Yes and No. Yes, we can pass arguments to methods and mutate the same in side the method body. No, there is no such thing as passing by reference in Java. All parameters/arguments in Java are always pass by value. Surprized?

Java does not have the concept of pointers. In case of primitives, the memory location at which the variable is defined holds the value of the variable. For example, writing int i = 5 creates a variable i at say memory location 100 which holds value 5. In case of objects, the object is created on the heap and its memory location address is stored as a value at the memory location where the reference to the object is created. For example, writing List myList = new ArrayList() creates an object of type ArrayList on the heap at say memory location 1000. A reference myList is created at a different memory location say 200 and the value stored at this memory location is 1000.

Suppose we were to call the above declared java method, the code fragment would be somthing like:


List myList = new ArrayList();
int count = 5;

ParameterPassing pp = new ParameterPassing();
pp.getName( myList, count );


Essentially what is getting passed is the value at the memory location of variables myList and count. myList is a reference to object and hence holds the address of the object created on heap whereas count is a primitive and directly holds the value. Thus in the getName method if we were to call the myList.add("xyz") method, then it will go and modify the object state on the heap. But if we do count++ within the getName method then the value is modified withing the method scope but not persisted back to the memory location where it originated from.

The crux of paramter passing in Java is as follows:
  1. Parameters/Arguments are always passed by value
  2. Objects are always mutated by reference


Another implementation detail to be kept in mind is that method invocation results into creation of local variables of the parameters passed to the method. Thus passing myList to getName method creates a local variable/reference to the ArrayList object created on the heap. Suppose in the method, we assign a different reference to the myList variable, myList = new ArrayList(), then this is valid only in the current method scope. This is because the locally created myList reference now points to a new object created on the heap.

A small program to explain the above concept:

import java.util.*;

public class ParameterPassing {

public String getName( List myList, int count ) {

myList.add("XYZ");
count++;

System.out.println(myList.get(0));
System.out.println(count);

myList = new ArrayList();

return "";
}

public static void main( String args[]) {

List myList = new ArrayList();
int count = 5;

ParameterPassing pp = new ParameterPassing();
pp.getName( myList, count );


System.out.println(myList.get(0));
System.out.println(count);
}
}

Following is the output:
XYZ
6
XYZ
5

The count in the main method holds the old value 5 because the count++ in getName method actually increments the local variable. Similarly myList = new ArrayList() points the local reference to the new object created on the heap.

1 comment:

eProjecthelp said...

Are you a expert in JAVA leverage your skills to others and gain huge benefits in doing so.. use our Project help and Training features.

Log on to eProjecthelp.com today.

www.eprojecthelp.com