Method Overloading


Method overloading occurs when you have two methods with exactly the same name, but each method takes a different number and/or different type of arguments.

An example you've already seen is in the PowerCalculator class we created. It contains two constructors- one that takes no arguments, and one that takes two arguments.

	public class PowerCalculator {

		private int result = 0;

		public PowerCalculator() {
			//empty constructor that does nothing
		}

		public PowerCalculator(int base, int exponent) {
			/*
			 * constructor that takes two arguments
			 * used for when you want to initialize the
			 * class with some start-up values
			 */

			result = calculatePower(base, exponent);
		}

		public int getResult() {
			// getter method for returning the result
			return result;
		}

		public void calculatePower(int base, int exponent) {
			result = 1;

			for ( int i=0; i<exponent; i++ ) {
				result *= base;
			}
		}
	}
The draw-back to this class is that it only calcuates the power of integer. What if we wanted to calculate the power of a long? Or a double? Or a float?

Let's make some changes to our PowerCalculator class so we can do that.

	public class PowerCalculator {

		public PowerCalculator() {
			//empty constructor that does nothing
		}

		public int calculatePower(int base, int exponent) {
			int result = 1;

			for ( int i=0; i<exponent; i++ ) {
				result *= base;
			}

			return result;
		}

		public long calculatePower(long base, int exponent) {
			long result = 1;

			for ( int i=0; i<exponent; i++ ) {
				result *= base;
			}

			return result;
		}

		public double calculatePower(double base, int exponent) {
			double result = 1;

			for ( int i=0; i<exponent; i++ ) {
				result *= base;
			}

			return result;
		}

		public float calculatePower(float base, int exponent) {
			float result = 1;

			for ( int i=0; i<exponent; i++ ) {
				result *= base;
			}

			return result;
		}
	}
I've made several changes here:

Got rid of the class-level variable Got rid of the 2nd constructor Got rid of the getter method Added 3 more calculatePower methods Made the calculatePower methods return a value

We now have a utility class for calculating the power of most numeric data types. The only difference between the calculatePower methods is the type of arguments being passed. This is what makes each method unique - the method signature is different because of the different data types as the arguments. The JVM will know which calculatePower method to use based on the data type passed as arguments.

This example uses the same number of arguments, just different data types, to create the unique method signatures. Another way is to change the number of arguments. Let's look at an example of a class for calculating pay:

	public class CalculatePay {

		private final int payPeriods = 24;

		public CalculatePay() {
		}

		public float calculatePay(float annualSalary) {
			/*
			 * for a salaried employees,
			 * divides annual salary by the number of pay periods
			 * /
			return annualSalary / payPeriods;
		}

		public float calculatePay(float hourlyWage, float hoursWorked) {
			/*
			 * for a hourly employees,
			 * multiplies hourly wage by hours worked
			 * /
			float fRetVal = 0;

			if ( hoursWorked > 40 ) {
				// if the emplyee worked overtime we need  to
				// account for those hours at time and a half
				fRetVal = 40 * hourlyWage
					+ (hoursWorked - 40 ) * hourlyWage * 1.5;
			} else {
				fRetVal = hourlyWage * hoursWorked;
			}

			return fRetVal;
		}
	}
A few notes here:

The method signatures are unique because they take a different number of arguments.

For the second method, I declared a local variable to store the return value. This is not necessary, I could have returned from inside the "if" or "else" as follows:

		if ( hoursWorked > 40 ) {
			return 40 * hourlyWage
				+ (hoursWorked - 40 ) * hourlyWage * 1.5;
		} else {
			return hourlyWage * hoursWorked;
		}
However, it is considered poor form to have multiple returns in a method. For very long methods, it can be diffuclt to trace when and where the method will exit. So, create a variable to store the return value, and use only one return statement at the very end of the method - that is the logical place for a return from a method.