Java allows a method to be overloaded. Method overloading occurs when a class has two or more methods with the same name but different parameter lists. Having more than one method with the same name might seem unnecessary, but method overloading is used quite frequently in Java (and other program- ming languages).
Method overloading is used most commonly with constructors, which are discussed in the next section.
For example, the println() method that we used throughout the book so far is an overloaded method of the java.io.PrintStream class, as you can see by the documentation of PrintStream shown in Figure 5.3.
Methods 121
♦ A Class with No main() Method?
A common point of confusion that new OOP students of mine have arises when they write a class that does not have main() method in it. A Java class without main() is not a program.
For example, you cannot execute the Radio class. The Radio class is a description (albeit a simple one) of an AM/FM radio. If you try to run Radio by entering the following command, you will get an error message from the JVM, stating that no main() method was found:
java Radio
The Radio class is meant to be used by other classes that need a radio.
In a large Java application with dozens or even hundreds of classes, you might define main() methods all over the place. However, it is likely that only one class has main() in it. If the Java application is using other Java technologies such as Servlets or Enterprise JavaBeans, no class will have a main() method in it.
On a similar note, just because Radio has a bunch of nice methods in it, it does not mean that the methods are automatically invoked. If you want a method to execute, you need to explicitly invoke it. Similarly, if you do not want a method to execute, don’t invoke it.
For example, the ListenToRadio program creates a Radio object, but at no point is the turnDown() method invoked. We could have invoked turnDown() if we wanted to because it is available to us, but we do not have to and it is not invoked automatically at any point in time.
Figure 5.3 The println() method is overloaded 10 times in the PrintStream class.
The PrintStream class has 10 println() methods. How does the compiler know which one you want to invoke? If you look carefully, you will also notice that the parameter list is different for each version of println(). For example, calling println() and passing in an int invokes that overloaded version whose signature is as follows:
public void println(int x)
Invoking println() and passing in a String invokes the following version:
public void println(String x)
If method overloading were not an option, the println() methods would each have to use a unique name such as printlnInt(), printlnString(), println- Double(), and so on. In this case, method overloading simplifies both the writing of the PrintStream class and the usage of the class. Developers do not need to remember 10 different names for printing a line of text to the system output; they can simply remember that the method to use is println(), and it is overloaded for every data type.
Let’s look at an example using method overloading. The following Calcula- tor class contains five multiply() methods. Study the method signatures care- fully and determine whether this is valid method overloading.
public class Calculator {
public int multiply(int x, int y) {
System.out.println(“Multiply int * int”); return x * y;
}
public double multiply(double x, double y) {
System.out.println(“Multiply double * double”); return x * y;
}
public double multiply(int x, double y) {
System.out.println(“Multiply int * double”); return x * y;
}
public int multiply(int x) {
System.out.println(“Multiply int * itself”); return x * x;
}
public int multiply(int x, int y, int z) {
System.out.println(“Multiply three ints”); return x * y * z;
} }
Methods 123
♦ Method Overloading
You can overload a method as long as the parameter lists are distinct enough for the com- piler to be able to distinguish which method you want to invoke. Certainly if the number of parameters is different, the overloading is valid, as shown in the following two method signatures:
public float computePay(double d, int x); //Two parameters public float computePay(double d); //One parameter
If you simply change the name of the parameter, it is not valid. For example, the follow- ing two methods could not appear in the same class because this is not valid overloading:
public void setDay(int x, int y, long z);
public boolean setDay(int a, int b, long c) //No!
The preceding two methods have the same name and the same number of parameters, and the parameters appear in the same order. The compiler would not be able to distin- guish between the two methods and would generate a compiler error. Note that changing the return value does not affect whether the overloading is valid or not.
However, changing the order of parameters is just like changing the parameter list. For example, the following two methods demonstrate valid method overloading:
public void setDay(int x, int y, long z ; public boolean setDay(long a, int b, int c);
Of the five multiply() methods in the Calculator class, the parameter lists are different for each one. Therefore, this is an example of valid method overloading. The following OverloadDemo program instantiates a Calculator object and invokes the various multiply() methods. Study the OverloadDemo program carefully and try to determine the output. The actual output is shown in Fig- ure 5.4.
public class OverloadDemo {
public static void main(String [] args) {
System.out.println(“Instantiating a Calculator...”); Calculator calc = new Calculator();
System.out.println(“Initializing some variables...”); int a = 5; int b = 8; double d1 = 2.5; double d2 = -1.0; float f = 4.0F; int intAnswer = 0; double doubleAnswer = 0.0; intAnswer = calc.multiply(a, b); System.out.println(a + “ * “ + b + “ = “ + intAnswer); doubleAnswer = calc.multiply(d1, d2); System.out.println(d1 + “ * “ + d2 + “ = “ + doubleAnswer); intAnswer = calc.multiply(b); System.out.println(b + “ * “ + b + “ = “ + intAnswer); intAnswer = calc.multiply(a, b, a);
System.out.println(a + “ * “ + b + “ * “ + a + “ = “ + intAnswer); doubleAnswer = calc.multiply(b, f); System.out.println(b + “ * “ + f + “ = “ + doubleAnswer); doubleAnswer = calc.multiply(d2, f); System.out.println(d2 + “ * “ + f + “ = “ + doubleAnswer); } }
Figure 5.4 Output of the OverloadDemo program. 124 Chapter 5
In the first call to multiply() in the OverloadDemo program, a and b are passed in. Because a and b are both ints, the following version of multiply() in the Calculator class is invoked:
public int multiply(int x, int y)
When the two doubles d1 and d2 are passed in to multiply(), the corre- sponding overloaded version in Calculator is invoked:
public double multiply(double x, double y)
In the following statement, only a single int is passed in, so the version of multiply that takes in a single int is invoked:
intAnswer = calc.multiply(b);
Similarly, invoking multiply() with three int arguments causes the corre- sponding multiply() with three int parameters to be invoked.
I want to make an observation about the following statement in the Over- loadDemo program:
doubleAnswer = calc.multiply(b, f);
The arguments are of type int and float, in that order. There is no multiply() method in the Calculator class that has a parameter list with an int and a float. However, because a float can be promoted to a double, notice that the multi- ply() method that gets invoked is the following:
public double multiply(int x, double y);
This situation in which the float is passed in to a double arises all the time when invoking methods (not just when a method is overloaded). When an argument does not exactly match a parameter, but the argument can be promoted to match a parameter, then the promotion will occur automatically.