|
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.
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 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.