next up previous contents
Next: Cloning Up: Java Interlude 2 Parameter Previous: Java Interlude 2 Parameter   Contents

Parameter passing in Java

In Java, scalar variables (i.e. of type int, long, short, float, double, byte, char, boolean) are always passed to functions by value, like in C. In other words, the value passed to the function is copied into the local parameter and any change to the local copy has no effect on the original copy.

Unlike C, there is no way to pass the address of a scalar. We cannot write the equivalent of the following code in C:

  int i,j;
  ...
  swap(&i,&j);
  ...

  void swap(int *p, int *q){
    int tmp;
    tmp = *p;
    *p = *q;
    *q = tmp;
  }

Objects (i.e., any variable that is not a scalar) are passed by reference, like arrays in C. Like C, the justification is that objects can be large structures and it would be inefficient to copy the structure. Notice, however, that (like in C), we can modify the contents of what a parameter points to, but we cannot modify where it points. If we want to swap the contents of two objects from the same class, we cannot write:

   class Myclass{
     ...
     public void swap(Myclass p){  // Swap "this" with p
       Myclass tmp;
       tmp = p;
       p = this;
       this = tmp;
     }
   }

Instead, we must write something like:

   class Myclass{
     ...
     public void swap(Myclass p){
       Myclass tmp = new Myclass(...);  // Make a new tmp object
       ... // Copy contents of p into tmp
       ... // Copy contents of this into p
       ... // Copy contents of tmp back into this
     }
   }

What about return values? Suppose we enhance the Employee class as follows:

  class Employee{
    private String name;
    private double salary;
    private Date joindate;

    // Constructor
    public Employee(String n, double s, int d, int m, int y){
       name = n; salary = s;
       joindate = new Date(d,m,y);  //
    }

    ... 
    // "accessor" methods
    public Date get_joindate(){ return joindate; }
    ...
  }

where Date is defined as follows:

  class Date{
    private int day, month, year;

    public Date(int d, int m, int y){
      day = d;
      month = m;
      year = y;
    }

    public void advance(int d){   // Modify day/month/year so that 
      ...                         // date advances by d days
    }
    ...
  }

Now, suppose we use get_joindate() as follows:

  Employee e = new Employee(...);
  Date d = e.get_joindate();
  d.advance(100); // e loses 100 days seniority!

The problem is that get_joindate() returns a reference to its private copy of Date and this reference can be used to invoke public methods on the Date object, though the Date object is supposed to be a private component of the Employee e.

The solution is to make a copy of the object before returning it.

  class Employee{
    ...
    public Date get_joindate(){ 
      Date tmpdate = new Date(...); // Construct tmpdate using
                                    // current values of joindate
      return tmpdate; 
    }
    ...
  }

Here, copying Date is not difficult because Date is itself a ``flat'' object and can be copied component-wise. If we have to make a copy of Employee, we have to first recursively make a copy of the nested object Date and then copy the scalars salary and name.


next up previous contents
Next: Cloning Up: Java Interlude 2 Parameter Previous: Java Interlude 2 Parameter   Contents
Madhavan Mukund 2004-04-29