Witscale Test Center

10.4 Object reference conversions > 10.4.4 Object reference conversion during a method call


10.4.4 Object reference conversion during a method call

Before we discuss the passing of object references as an argument to the methods, let us see how the arguments are passed to a method and what happens if that method modifies the argument.

Passing arguments to a method

When you pass an argument to a method, actually a copy of that argument is passed. Since the method gets a copy, if it makes any modifications to that argument, they are not reflected in the original value. Listing 10.1 calls method modify() that changes the value of its argument.




When the execution control returns from modify(),  the value of variable a is not changed. Since the copy of a is passed to the method modify(), a is still 10 after the method is executed. This is also true in case of object references. For instance, when a reference is passed to a method, a copy of that reference is passed. But the interesting thing about reference is that the copy of the object reference still points to an original object. So when an object reference is passed to a method, it is possible to change the object within that method. Listing 10.2 shows a method modify() that adds new elements to its argument vector.

When the execution control returns from modify(),  the vector names is now changed, it has one element in it. A copy of names is passed to the method modify(), but this copy points to the Vector object created in main method. When method modify()adds an element, it is added to this vector object. The reference conversion rules do not depend on whether the method modifies the object or not. However, it is an important know-how about argument passing during method calls.

Rules of reference converstion in a method call

The rules of object reference conversion during method calls are exactly same as the assignments. Like assignments where you can assign a narrower data type to a wider type, you can pass a narrower data type to a method that expects a wider type. For instance, you can pass an argument of class-type to a method, which expects its super class’s type of argument. If the method accepts a wider datatype argument, it does automatic type conversion when argument of narrower type is passed. Following is a quick summary of reference conversion in the context of method call.

 

1.       If a method accepts argument of a class-type, you can pass a reference of its subclasses to it.

For example, if we have method addAccount() which takes argument of class-type Account as:

 

public void addAccount(Account newAccount) {}

 

Now you can pass reference of any of the subclasses of Account as an argument. Following are some valid ways of calling this method.

 

SavingsAccount savingsAcc = new SavingsAccount();

addAccount(savingsAcc);                      // valid method call

addAccount(new CheckingAccount());           // valid method call

 

2.       If a method that accepts argument of interface-type, you can pass reference of any class (type) that implements that interface.

For example, if we have method isAuditable() which takes argument of interface-type
Auditable as:

 

public boolean isAuditable(Auditable auditable) {}

 

Then following are some valid ways of calling this method

 

Account acc = new Account();

if(isAuditable(acc))             // valid method call

  System.out.println(“Account is auditable”);

 

The method isAuditable()takes argument of interface-type Auditable. Therefore, it can accept a reference of Account type as that class implements Auditable.

 

3.       If a method that accepts argument of interface-type, you can pass a reference of any of its sub-interface types.

For example, if we have method isReviewable() which takes argument of interface-type
Reviewable as:

 

public boolean isReviewable(Reviewable reviewable) {}

 

Then following are some valid ways of calling this method

 

Account acc = new Account();

Auditable auditableAcc = acc;

if(isReviewable(auditableAcc))               // valid method call

  System.out.println(“Account is reviewable”);

 

The method isReviewable()takes argument of interface-type Reviewable. Therefore, it can accept a reference of Auditable type as Auditable is a sub-interface of Reviewable.

 

4.       You can pass array to any method that accepts java.lang.Object, Serializable or Cloneable type of arguments.

For example, consider a  method isEqual() that takes arguments of class-type Object as:

 

public boolean isEqual(Object object1, Object object2) {}

 

You can call this method by passing any two object references. The following code calls the method with two array references:

 

int[] intArray1 = new int[5];

int[] intArray2 = new int[5];

if(isEqual(intArray1, intArray2)) // valid method call

  System.out.println(“Arrays are equal”);

 

5.       You can pass array of object references to a method that accepts array of object references only if elements of array you pass are of narrower type. 

For instance, you can pass CheckingAccount[] reference to a method that takes Account[] reference because CheckingAccount is a narrower type than Account. Assume that there is a method processAll() that accepts array reference of type Account[] as:

 

public void processAll(Account[] accounts) {}

 

You can call this method by passing references of narrower types such as CheckingAccount[] or SavingsAccount[]. Following are all valid ways of calling this method.

 

CheckingAccount[] chkAccounts = new CheckingAccount[];

processAll(chkAccounts);   //valid method call

 

SavingsAccount[] savingsAccounts = new SavingsAccount[];

processAll(savingsAccounts);     //valid method call

  

Since Account is a superclass of both CheckingAccount and SavingsAccount, you can pass arguments of type CheckingAccount[] and SavingsAccount[] to the method processAll().

 

The discussion of object reference conversion ends with these rules. Even though there seem to be lot of complex rules, they all work roughly on the same principle, “Java automatically converts type from narrower to wider”. The reference type is considered wider if it is at the upper–level in the class hierarchy. Hence, superclass of a class, the interface it implements are considered wider types than the class itself. Besides conversion, you can also change the reference type explicitly with casting.