Java Advanced Placement Study Guide:  Method Overloading

Sample question:  Is it necessary to define all versions of an overloaded method in the same class?

Published: March 6, 2002
By Richard G. Baldwin

Questions

File JavaAP014.htm


Welcome

This is one in a miniseries of tutorial lessons designed to help you learn the essential features of Java object-oriented programming as identified by The College Board.

Purpose

The purpose of this miniseries is to help you study for the Advanced Placement Examinations designed by the College Board.

Once you understand everything in this miniseries, plus the material in the lessons that I published earlier on Java Data Structures, you should understand the Java programming features that the College Board considers essential for the first two semesters of object-oriented programming education at the university level.

Approach

These lessons provide questions, answers, and explanations designed to help you to understand the subset of Java features covered by the Java Advanced Placement Examinations (as of October, 2001).

Please see the first lesson in the miniseries entitled Java Advanced Placement Study Guide: Introduction to the Lessons, Primitive Types, for additional background information.  The previous lesson was entitled Java Advanced Placement Study Guide:  More on Arrays.

Supplementary material

In addition to the material in these lessons, I recommend that you also study the other lessons in my extensive collection of online Java tutorials, which are designed from a more conventional textbook approach.  You will find those lessons published at Gamelan.com.  However, as of the date of this writing, Gamelan doesn't maintain a consolidated index of my Java tutorial lessons, and sometimes they are difficult to locate there.  You will find a consolidated index at Baldwin's Java Programming Tutorials.

What is Included?

Click here for a preview of the Java programming features covered by this lesson.



1.  What output is produced by the following program?
public class Ap079{
  public static void main(
                        String args[]){
    new Worker().doOverLoad();
  }//end main()
}//end class definition

class Worker{
  public void doOverLoad(){
    int x = 3;
    double y = 4.2;
    System.out.println(square(x) + " "
                          + square(y));
  }//end doOverLoad()
    
  public int square(int y){
    return y*y;
  }//end square()
    
  public double square(double y){
    return y*y;
  }//end square()
}// end class

Answer and Explanation

2.  What output is produced by the following program?

public class Ap080{
  public static void main(
                        String args[]){
    new Worker().doOverLoad();
  }//end main()
}//end class definition

class Worker{
  public void doOverLoad(){
    int x = 3;
    double y = 4.2;

    System.out.print(square(x) + " ");
    System.out.print(square(y));
    System.out.println();
  }//end doOverLoad()
    
  public float square(float y){
    System.out.print("float ");
    return y*y;
  }//end square()
    
  public double square(double y){
    System.out.print("double ");
    return y*y;
  }//end square()
}// end class

Answer and Explanation

3.  What output is produced by the following program?

public class Ap081{
  public static void main(
                        String args[]){
    new Worker().doOverLoad();
  }//end main()
}//end class definition

class Worker{
  public void doOverLoad(){
    double w = 3.2;
    double x = 4.2;
    
    int y = square(w);
    double z = square(x);
    
    System.out.println(y + " " + z);
  }//end doOverLoad()
    
  public int square(double y){
    return (int)(y*y);
  }//end square()
  
  public double square(double y){
    return y*y;
  }//end square()

}// end class

Answer and Explanation

4.  What output is produced by the following program?

public class Ap082{
  public static void main(
                        String args[]){
    new Worker().doOverLoad();
  }//end main()
}//end class definition

class Worker{
  public void doOverLoad(){
    int w = 3;
    double x = 4.2;
    
    System.out.println(
      new Subclass().square(w) + " "
      + new Subclass().square(x));
  }//end doOverLoad()
}// end class

class Superclass{
  public int square(int y){
    return y*y;
  }//end square()
}//end class Superclass

class Subclass extends Superclass{
  public double square(double y){
    return y*y;
  }//end square()
}//end class Subclass

Answer and Explanation

5.  What output is produced by the following program?

public class Ap083{
  public static void main(
                        String args[]){
    new Worker().doOverLoad();
  }//end main()
}//end class definition

class Worker{
  public void doOverLoad(){
    int w = 3;
    double x = 4.2;

    System.out.println(
      new Subclass().square(w) + " "
      + new Subclass().square(x));
  }//end doOverLoad()
}// end class

class Superclass{
  public double square(double y){
    return y*y;
  }//end square()
}//end class Superclass

class Subclass extends Superclass{
  public int square(int y){
    return y*y;
  }//end square()
}//end class Subclass

Answer and Explanation

6.  What output is produced by the following program?

public class Ap084{
  public static void main(
                        String args[]){
    new Worker().doOverLoad();
  }//end main()
}//end class definition

class Worker{
  public void doOverLoad(){
    int x = 2147483647;
    square(x);
    long y = 9223372036854775807L;
    square(y);
    double z = 4.2;
    square(z);
    
    System.out.println();
  }//end doOverLoad()
    
  public void square(float y){
    System.out.println("float" + " " +
                              y + " ");
  }//end square()
    
  public void square(double y){
    System.out.println("double" + " " +
                              y + " ");
  }//end square()
}// end class

Answer and Explanation

7.  What output is produced by the following program?

public class Ap085{
  public static void main(
                        String args[]){
    new Worker().doOverLoad();
  }//end main()
}//end class definition

class Worker{
  public void doOverLoad(){
    Test a = new Test();
    DumIntfc b = new Test();
    overLoadMthd(a);
    overLoadMthd(b);
    System.out.println();
  }//end doOverLoad()
    
  public void overLoadMthd(Test x){
    System.out.print("Test ");
  }//end overLoadMthd
  
  public void overLoadMthd(DumIntfc x){
    System.out.print("DumIntfc ");
  }//end overLoadMthd
}// end class

interface DumIntfc{
}//end DumIntfc

class Test implements DumIntfc{
}//end class Test

Answer and Explanation

8.  What output is produced by the following program?

public class Ap086{
  public static void main(
                        String args[]){
    new Worker().doOverLoad();
  }//end main()
}//end class definition

class Worker{
  public void doOverLoad(){
    Test a = new Test();
    Object b = new Test();
    overLoadMthd(a);
    overLoadMthd(b);
    System.out.println();
  }//end doOverLoad()
    
  public void overLoadMthd(Test x){
    System.out.print("Test ");
  }//end overLoadMthd
  
  public void overLoadMthd(Object x){
    System.out.print("Object ");
  }//end overLoadMthd

}// end class

class Test{
}//end class Test

Answer and Explanation

9.  What output is produced by the following program?

public class Ap087{
  public static void main(
                        String args[]){
    new Worker().doOverLoad();
  }//end main()
}//end class definition

class Worker{
  public void doOverLoad(){
    SubC a = new SubC();
    SuperC b = new SubC();

    SubC obj = new SubC();
    obj.overLoadMthd(a);
    obj.overLoadMthd(b);

    System.out.println();
  }//end doOverLoad()

}// end class

class SuperC{
  public void overLoadMthd(SuperC x){
    System.out.print("SuperC ");
  }//end overLoadMthd
}//end SuperC

class SubC extends SuperC{
  public void overLoadMthd(SubC x){
    System.out.print("SubC ");
  }//end overLoadMthd
}//end class SubC

Answer and Explanation

10.  What output is produced by the following program?

public class Ap088{
  public static void main(
                        String args[]){
    new Worker().doOverLoad();
  }//end main()
}//end class definition

class Worker{
  public void doOverLoad(){
    SubC a = new SubC();
    SuperC b = new SubC();

    SubC obj = new SubC();
    obj.overLoadMthd(a);
    obj.overLoadMthd(b);

    System.out.println();
  }//end doOverLoad()

}// end class

class SuperC{
  public void overLoadMthd(SubC x){
    System.out.print("SubC ");
  }//end overLoadMthd
}//end SuperC

class SubC extends SuperC{
  public void overLoadMthd(SuperC x){
    System.out.print("SuperC ");
  }//end overLoadMthd
}//end class SubC

Answer and Explanation



Copyright 2002, Richard G. Baldwin.  Reproduction in whole or in part in any form or medium without express written permission from Richard Baldwin is prohibited.

About the author

Richard Baldwin is a college professor (at Austin Community College in Austin, TX) and private consultant whose primary focus is a combination of Java and XML. In addition to the many platform-independent benefits of Java applications, he believes that a combination of Java and XML will become the primary driving force in the delivery of structured information on the Web.

Richard has participated in numerous consulting projects involving Java, XML, or a combination of the two.  He frequently provides onsite Java and/or XML training at the high-tech companies located in and around Austin, Texas.  He is the author of Baldwin's Java Programming Tutorials, which has gained a worldwide following among experienced and aspiring Java programmers. He has also published articles on Java Programming in Java Pro magazine.

Richard holds an MSEE degree from Southern Methodist University and has many years of experience in the application of computer technology to real-world problems.

baldwin.richard@iname.com


What is Included?


According to the subset document,

"Method overloading (e.g. MyClass.foo(String s) and MyClass.foo(int n)) is part of the AP CS subset. However, there will be no "trick questions" that test an understanding of the subtleties of the overloading resolution mechanism."
(I believe that the comment about trick questions has been removed from a revised version the subset document.)


Answers and Explanations

Answer 10

A.  Compiler Error

Back to Question 10

Explanation 10

Oops!

Oops, just when we thought that we were in the clear, we're back into the subtleties of the overloading resolution mechanism again.

Swapped the method locations

This program is the same as the program from Question 9, except that I swapped the positions of the two overloaded versions of the method named overLoadMthd() between the subclass and the superclass.

The version of the overloaded method that requires an incoming parameter of type SubC is now defined in the class named SuperC, and the version that requires an incoming parameter of type SuperC is defined in the class named SubC.

An ambiguous situation

This program produces the following compiler error:

Ap088.java:20: reference to overLoadMthd is ambiguous, both method overLoadMthd(SubC) in SuperC and method overLoadMthd(SuperC) in SubC match
    obj.overLoadMthd(a);

While this is a subtle problem, it should not come as a surprise to you.  This is essentially the same problem that was exposed in Question 4.  The only difference is that the program in Question 4 dealt with method parameters of primitive types, and this program deals with method parameters of class types.

The basic problem

The basic problem is the same.  Placing an assignment compatible version of an overloaded method further down the inheritance hierarchy than a matching version causes the matching version to be blocked when looking up from below.

Could be resolved using method overriding

As was the case in Question 4, this problem could be resolved by providing an overridden version of the method in the lower class and using the super keyword to invoke the version in the higher class.

Method overriding will be the topic of a future lesson.

Answer 9

C.  SubC SuperC

Back to Question 9

Explanation 9

While admittedly a little convoluted, this is another relatively straightforward application of method overloading using types from the class hierarchy.

Type SubC, SuperC, or Object

This method defines a class named SuperC, which extends Object, and a class named SubC, which extends SuperC.  Therefore, an object instantiated from the class named SubC can be treated as any of the following types:  SubC, SuperC, or Object.

Two overloaded methods in different classes

Two overloaded methods named overLoadMthd() are defined in two classes in the inheritance hierarchy.  The class named SuperC defines a version that requires an incoming parameter of type SuperC.  The class named SubC defines a version that requires an incoming parameter of type SubC.  When invoked, each of these overloaded methods prints the type of its formal argument.

Two objects of type SubC

The program instantiates two objects of the SubC class, storing the reference to one of them in a reference variable of type SubC, and storing the reference to the other in a reference variable of type SuperC.

Invoke the overloaded method twice

The next step is to invoke the overloaded method named overLoadMthd() twice in succession, passing each of the reference variables of type SubC and SuperC to the method.

Instance methods require an object

Because the two versions of the overloaded method are instance methods, it is necessary to have an object on which to invoke the methods.  This is accomplished by instantiating a new object of the SubC class, storing the reference to that object in a reference variable named obj, and invoking the overloaded method on that reference.

Overloaded methods not in same class

The important point here is that the two versions of the overloaded method were not defined in the same class.  Rather, they were defined in two different classes in the inheritance hierarchy.  However, they were defined in such a way that both overloaded versions were contained as instance methods in an object instantiated from the class named SubC.

No surprises

There were no surprises.  When the overloaded method was invoked twice in succession, passing the two different reference variables as parameters, the output shows that the version that was invoked in each case had a formal argument type that matched the type of the parameter that was passed to the method.

Answer 8

C.  Test Object

Back to Question 8

Explanation 8

Another straightforward application

This is another straightforward application of method overloading, which produces no surprises.

This program defines a new class named Test, which extends the Object class.  This means that an object instantiated from the class named Test can be treated either as type Test, or as type Object.

The program defines two overloaded methods named overLoadMthd().  One requires an incoming parameter of type Test.  The other requires an incoming parameter of type Object.  When invoked, each of these methods prints the type of its incoming parameter.

The program instantiates two different objects of the class Test, storing a reference to one of them in a reference variable of type
Test, and storing a reference to the other in a reference variable of type Object.

No surprises here

Then it invokes the overloaded overLoadMthd() method twice in succession, passing the reference of type Test during the first invocation, and passing the reference of type Object during the second invocation.

As mentioned above, the output produces no surprises.  The output indicates that the method selected for execution during each invocation is the method with the formal argument type that matches the type of parameter passed to the method.
 

Answer 7

C.  Test DumIntfc

Back to Question 7

Explanation 7

Overloaded methods with reference parameters

This is a fairly straightforward application of method overloading.  However, rather than requiring method parameters of primitive types as in the previous questions in this lesson, the overloaded methods in this program require incoming parameters of class and interface types respectively.

Type Test or type DumIntfc

The program defines an interface named DumIntfc and defines a class named Test that implements that interface.  The result is that an object instantiated from the Test class can be treated either as type Test or as type DumIntfc (it could also be treated as type Object as well).

Two overloaded methods

The program defines two overloaded methods named overLoadMthd().  One requires an incoming parameter of type Test, and the other requires an incoming parameter of type DumIntfc.  When invoked, each of the overloaded methods prints a message indicating the type of its argument.

Two objects of the class Test

The program instantiates two objects of the class Test.  It assigns a reference to one of those objects to a reference variable named a, which is declared to be of type Test.

The program assigns a reference to the other object of the class Test to a reference variable named b, which is declared to be of type DumIntfc.

No surprises here

Then it invokes the overloaded method named overLoadMthd() twice in succession, passing first the reference variable of type Test and then the reference variable of type DumIntfc.

The program output doesn't produce any surprises.  When the reference variable of type Test is passed as a parameter, the overloaded method requiring that type of parameter is selected for execution.  When the reference variable of type DumIntfc is passed as a parameter, the overloaded method requiring that type of parameter is selected for execution.

Answer 6

float 2.14748365E9
float 9.223372E18
double 4.2

Back to Question 6

Explanation 6

Another subtle method selection issue

This program illustrates a subtle issue in the automatic selection of an overloaded method based on assignment compatibility.

This program defines two overloaded methods named square().  One requires an incoming parameter of type float, and the other requires an incoming parameter of type double.

When invoked, each of these methods prints the type of its formal argument along with the value of the incoming parameter as represented by its formal argument type.  In other words, the value of the incoming parameter is printed after it has been automatically converted to the formal argument type.

Printout identifies the selected method

This printout makes it possible to determine which version is invoked for different types of parameters.  It also makes it possible to determine the effect of the automatic conversion on the incoming parameter.  What we are going to see is that the conversion process can introduce serious accuracy problems.

Invoke the method three times

The square() method is invoked three times in succession, passing values of type int, long, and double during successive invocations.

(Note, type long is apparently not included on the AP CS exam.  Suffice it to say that it is a 64-bit integer type capable of storing integer values that are much larger than can be stored in type int.  The use of this type here is important for illustration of data corruption that occurs through automatic type conversion.)
The third invocation of the square() method, passing a double as a parameter, is not particularly interesting.  There is a version of square() with a matching argument type, and everything behaves as would be expected for this invocation.  The interesting behavior occurs when the int and long values are passed as parameters.

Passing an int parameter

The first thing to note is the behavior of the program produced by the following code fragment.
 
    int x = 2147483647;
    square(x);

The above fragment assigns a large integer value (2147483647) to the int variable x and passes that variable to the square() method.  This fragment produces the following output on the screen:

float 2.14748365E9

As you can see, the system selected the overloaded method that requires an incoming parameter of type float for execution in this case (rather than the version that requires type double).

Conversion from int to float loses accuracy

Correspondingly, it converted the incoming int value to type float, losing one decimal digit of accuracy in the process. (The original int value contained ten digits of accuracy.  This was approximated by a nine-digit float value with an exponent value of 9.)

This seems like an unfortunate choice of overloaded method.  Selecting the other version that requires a double parameter as input would not have resulted in any loss of accuracy.

A more dramatic case

Now, consider an even more dramatic case, as illustrated in the following fragment where a very large long integer value (9223372036854775807) is passed to the square() method.
 
    long y = 9223372036854775807L;
    square(y);

The above code fragment produced the following output:

float 9.223372E18

A very serious loss of accuracy

Again, unfortunately, the system selected the version of the square() method that requires a float parameter for execution.  This caused the long integer to be converted to a float.  As a result, the long value containing 19 digits of accuracy was converted to an estimate consisting of only seven digits plus an exponent.

(Even if the overloaded square method requiring a double parameter had been selected, the conversion process would have lost about three digits of accuracy, but that would have been much better than losing twelve digits of accuracy.)
The moral to the story is ...

Don't assume that just because the system knows how to automatically convert your integer data to floating data, it will protect the integrity of your data.  Oftentimes it won't.

To be really save ...

To be really safe, whenever you need to convert either int or long types to floating format, you should write your code in such a way as to ensure that it will be converted to type double instead of type float.

For example, the following modification would solve the problem for the int data and would greatly reduce the magnitude of the problem for the long data.  Note the use of the (double) cast to force that version of the square() method to be selected for execution.
 
    int x = 2147483647;
    square((double)x);
    long y = 9223372036854775807L;
    square((double)y);

The above modification would cause the program to produce the following output:

double 2.147483647E9
double 9.223372036854776E18
double 4.2

This output shows no loss of accuracy for the int value, and the loss of three digits of accuracy for the long value.

(Because a long and a double both store their data in 64 bits, it is not possible to convert a very large long value to a double value without some loss in accuracy, but even that is much better than converting a 64-bit long value to a 32-bit floatvalue.)

Answer 5

C.  9 17.64

Back to Question 5

Explanation 5

Swap method locations

This program is just like the program with the ambiguity problem from Question 4 with one major difference.  I swapped the locations of the overloaded versions of the method named square() in the inheritance hierarchy.

In this case, the overloaded version of the method square() that requires the wider parameter type, double, is defined further up the inheritance hierarchy than the version that requires the narrower parameter type, int.  As a result, the program compiles and executes properly.

A subtle difference

When the square() method is invoked on an object of the Subclass type passing an int as a parameter, there is an exact match to the required parameter type of the square() method defined in that class.  Thus, there is no ambiguity.

When the square() method is invoked on an object of the Subclass type passing a double as a parameter, the version of the square() method defined in the Subclass type is not selected.  The double value is not assignment compatible with the required type of the parameter (an int is narrower than a double).  Thus, there is no ambiguity.

Having made that determination, the system continues searching for an overloaded method with a required parameter that is either type double or assignment compatible with double.  It finds the inherited version that requires a double parameter and invokes it.

Answer 4

A.  Compiler Error

Back to Question 4

Explanation 4

Back to the subtle issues

The problem that prevented this program from compiling is very subtle.

This program defines a class hierarchy consisting of:

Two overloaded versions of a method named square() are defined.  One of the overloaded versions, which requires a single incoming parameter of type int, is defined in the class named Superclass.   The other overloaded version, which requires a single incoming parameter of type double, is defined in the class named Subclass.

A valid arrangement for overloaded methods

Overloaded methods need not all be defined in the same class.  They can be defined up and down the inheritance hierarchy.  The requirement is simply that two or more versions of the overloaded method belong to, or be inherited into, an object instantiated from a class at some level in the inheritance hierarchy.

In this case, an object instantiated from the class named Subclass will contain two overloaded instance methods named square().  One is defined in the Subclass class from which the object is instantiated.  The other is inherited from the class named Superclass.

Two anonymous objects

The program instantiates two anonymous objects of the class named Subclass.  It invokes the square() method on one of those objects, passing a double value as a parameter.  There is no problem with this method invocation.  The method parameter is a perfect match for the overloaded method named square() that is defined in the class named Subclass.

An ambiguous situation

The program also invokes the square() method on the other object, passing a parameter of type int.  This is where a problem arises.  The incoming parameter is directly compatible with the formal argument of the square() method inherited from Superclass.  It is also assignment compatible with the formal parameter of the square() method defined in the class named Subclass.  The compiler must decide which method to invoke.  It refuses to make a decision, producing the following compiler error:

Ap082.java:18: reference to square is ambiguous, both method square(int) in Superclass and method square(double) in Subclass match
      new Subclass().square(w) + " "

If the compiler cannot select ...

Apparently this is one of those cases described by Mark Grand as follows, "If the compiler cannot select one of the methods as a better match than the others, the method selection process fails and the compiler issues an error message."

Could be a serious problem

This could be a serious problem in the design of a program.  Basically, the existence of the square() method requiring a parameter of type double in Subclass blocks access to the overloaded square() method in Superclass.

Overriding to the rescue

Although method overriding is not the topic of this lesson, the author of the class named Subclass could solve this problem by overriding the inherited square() method for a parameter of type int, using the super keyword to gain access to the blocked square() method.  Such a solution is shown below.  At this point, you can begin to see that overloading and overriding methods are somewhat related strategies.
 
  public int square(int y){
    return super.square(y);
  }//end square()

Answer 3

A.  Compiler Error

Back to Question 3

Explanation 3

Return type is not a differentiating feature

This is not a subtle issue.  This program illustrates the important fact that the return type does not differentiate between overloaded methods having the same name and formal argument list.

For a method to be overloaded, two or more versions of the method must have the same name and different formal arguments lists.

The return type can be the same, or it can be different (it can even be void).  It doesn't matter.

These two methods are not a valid overload

This program attempts to define two methods named square(), each of which requires a single incoming parameter of type double.  One of the methods casts its return value to type int and returns type int.  The other method returns type double.

The JDK 1.3 compiler produced the following error:

Ap081.java:28: square(double) is already defined in Worker
  public double square(double y){

Answer 2

C.  float 9.0 double 17.64

Back to Question 2

Explanation 2

This program is a little more subtle

Once again, the program defines two overloaded methods named square.  However, in this case, one of the methods requires a single incoming parameter of type float and the other requires a single incoming parameter of type double.

(The AP CS exam apparently doesn't cover the float type.  Suffice it to say that the float type is similar to the double type, but with less precision.  It is a floating type, not an integer type.  The double type is a 64-bit floating type and the float type is a 32-bit floating type.)
Passing a type int as a parameter

This program does not define a method named square() that requires an incoming parameter of type int.  However, the program invokes the square() method passing a value of type int as a parameter.

What happens to the int parameter?

The first question to ask is, will this cause one of the two overloaded methods to be invoked, or will it cause a compiler error?  The answer is that it will cause one of the overloaded methods to be invoked because a value of type int is assignment compatible with type float and type double.

Which overloaded method will be invoked?

Since the type int is assignment compatible with type float and also with type double, the next question is, which of the two overloaded methods will be invoked when a value of type int is passed as a parameter?

Learn through experimentation

I placed a print statement in each of the overloaded methods to display the type of that method's argument on the screen when the method is invoked.  By examining the output, we can see that the method with the float parameter was invoked first (corresponding to the parameter of type int). Then the method with the double parameter was invoked (corresponding to the parameter of type double).

Converted int to float

Thus, the system selected the overloaded method requiring an incoming parameter of type float when the method was called passing an int as a parameter.  The value of type int was automatically converted to type float.

In this case, it wasn't too important which method was invoked to process the parameter of type int, because the two methods do essentially the same thing -- compute and return the square of the incoming value.

However, if the behavior of the two methods were different from one another, it could make a lot of difference, which one gets invoked on an assignment compatible basis.

(Even in this case, it makes some difference.  As we will see later, when a very large int value is converted to a float, there is some loss in accuracy.  However, when the same very large int value is converted to a double, there is no loss in accuracy.)
Avoiding the problem

One way to avoid this kind of subtle issue is to avoid passing assignment-compatible values to overloaded methods.

Passing assignment-compatible values to overloaded methods allows the system to resolve the issue through automatic type conversion.  Automatic type conversion doesn't always provide the best choice.

Using a cast to force your choice of method

Usually, you can cast the parameter values to a specific type before invoking the method and force the system to select your overloaded method of choice.

For example, in this problem, you could force the method with the double parameter to handle the parameter of type int by using the following cast when the method named square() is invoked:

square((double)x)

However, as we will see later, casting may not be the solution in every case.

Answer 1

C.  9 17.64

Back to Question 1

Explanation 1

What is method overloading?

A rigorous definition of method overloading is very involved and won't be presented here.  However, from a practical viewpoint, a method is overloaded when two or more methods having the same name and different formal argument lists are defined in the class from which an object is instantiated, or are inherited into an object by way of superclasses of that class.

How does the compiler select among overloaded methods?

The exact manner in which the system determines which method to invoke in each particular case is also very involved.  Basically, the system determines which of the overloaded methods to execute by matching the types of  parameters passed to the method to the types of arguments defined in the formal argument list.

Assignment compatible matching

However, there are a number of subtle issues that arise, particularly when there isn't an exact match.  In selecting the version of the method to invoke, Java supports the concept of an "assignment compatible" match (or possibly more than one assignment compatible match).

Briefly, assignment compatibility means that it would be allowable to assign a value of the type that is passed as a parameter to a variable whose type matches the specified argument in the formal argument list.

Selecting the best match

According to Java Language Reference by Mark Grand, "If more than one method is compatible with the given arguments, the method that most closely matches the given parameters is selected.  If the compiler cannot select one of the methods as a better match than the others, the method selection process fails and the compiler issues an error message."

No trick questions

Fortunately, the AP CS subset document states,  "there will be no trick questions that test an understanding of the subtleties of the overloading resolution mechanism."

Understanding subtleties

On the other hand, if you plan to be a Java programmer, you must have some understanding of the subtle issues involving overloaded methods, and the relationship between overloaded methods and overridden methods.  Therefore, the programs in this lesson will provide some of that information and discuss some of the subtle issues that arise.

Even if you don't care about the subtle issues regarding method overloading, many of those issues really involve subtle issues regarding automatic type conversion.  You should study these questions to learn about the problems associated with automatic type conversion.

This program is straightforward

However, there isn't anything subtle about the program for Question 1.  This program defines two overloaded methods named square().  One requires a single incoming parameter of type int.  The other requires a single incoming parameter of type double.  Each method calculates and returns the square of the incoming parameter.

The program invokes a method named square twice in succession, and displays the values returned by those two invocations.  In the first case, an int value is passed as a parameter.  This causes the method with the formal argument list of type int to be invoked.

In the second case, a double value is passed as a parameter.  This causes the method with the formal argument list of type double to be invoked.

Overloaded methods may have different return types

Note in particular that the overloaded methods have different return types.  One method returns its value as type int and the other returns its value as type double.  This is reflected in the output format for the two return vales as shown below:

9 17.64



Copyright 2002, Richard G. Baldwin.  Reproduction in whole or in part in any form or medium without express written permission from Richard Baldwin is prohibited.

About the author

Richard Baldwin is a college professor (at Austin Community College in Austin, TX) and private consultant whose primary focus is a combination of Java and XML. In addition to the many platform-independent benefits of Java applications, he believes that a combination of Java and XML will become the primary driving force in the delivery of structured information on the Web.

Richard has participated in numerous consulting projects involving Java, XML, or a combination of the two.  He frequently provides onsite Java and/or XML training at the high-tech companies located in and around Austin, Texas.  He is the author of Baldwin's Java Programming Tutorials, which has gained a worldwide following among experienced and aspiring Java programmers. He has also published articles on Java Programming in Java Pro magazine.

Richard holds an MSEE degree from Southern Methodist University and has many years of experience in the application of computer technology to real-world problems.

baldwin.richard@iname.com

-end-