Chapter: Java The Complete Reference - The Java Language - A Closer Look at Methods and Classes

| Study Material, Lecturing Notes, Assignment, Reference, Wiki description explanation, brief detail |

Overloading Methods - Java

In Java, it is possible to define two or more methods within the same class that share the same name, as long as their parameter declarations are different.

Overloading Methods

 

In Java, it is possible to define two or more methods within the same class that share the same name, as long as their parameter declarations are different. When this is the case, the methods are said to be overloaded, and the process is referred to as method overloading. Method overloading is one of the ways that Java supports polymorphism. If you have never used a language that allows the overloading of methods, then the concept may seem strange at first. But as you will see, method overloading is one of Java’s most exciting and useful features.

 

When an overloaded method is invoked, Java uses the type and/or number of arguments as its guide to determine which version of the overloaded method to actually call. Thus, overloaded methods must differ in the type and/or number of their parameters. While overloaded methods may have different return types, the return type alone is insufficient to distinguish two versions of a method. When Java encounters a call to an overloaded method, it simply executes the version of the method whose parameters match the arguments used in the call.

 

Here is a simple example that illustrates method overloading:

 

// Demonstrate method overloading. 


class OverloadDemo {

 

void test() {

 

System.out.println("No parameters");

 

}

 

// Overload test for one integer parameter. 


void test(int a) {

 

System.out.println("a: " + a);

}

     Overload test for two integer parameters. void test(int a, int b) {

 

System.out.println("a and b: " + a + " " + b);

 

}

 

     Overload test for a double parameter

 

double test(double a) { System.out.println("double a: " + a); return a*a;

 

}

 

}

 

class Overload {

 

public static void main(String args[]) { OverloadDemo ob = new OverloadDemo(); double result;

 

// call all versions of test() 


ob.test();

 

ob.test(10); ob.test(10, 20);

 

result = ob.test(123.25);

 

System.out.println("Result of ob.test(123.25): " + result);

 

}

 

}

 

This program generates the following output:

 

No parameters a: 10

 

a and b: 10 20 double a: 123.25

 

Result of ob.test(123.25): 15190.5625

 

As you can see, test( ) is overloaded four times. The first version takes no parameters, the second takes one integer parameter, the third takes two integer parameters, and the fourth takes one double parameter. The fact that the fourth version of test( ) also returns a value is of no consequence relative to overloading, since return types do not play a role in overload resolution.

 

When an overloaded method is called, Java looks for a match between the arguments used to call the method and the method’s parameters. However, this match need not always be exact. In some cases, Java’s automatic type conversions can play a role in overload resolution. For example, consider the following program:

 

// Automatic type conversions apply to overloading. 


class OverloadDemo {

 

void test() {

 

System.out.println("No parameters");

 

}

 

// Overload test for two integer parameters. 


void test(int a, int b) {

 

System.out.println("a and b: " + a + " " + b);

}

 

// Overload test for a double parameter 


void test(double a) {

 

System.out.println("Inside test(double) a: " + a);

 

}

 

}

 

class Overload {

 

public static void main(String args[]) { OverloadDemo ob = new OverloadDemo(); int i = 88;

 

ob.test(); ob.test(10, 20);

 

ob.test(i); // this will invoke test(double) ob.test(123.2); // this will invoke test(double)

 

}

 

}

This program generates the following output:

 

No parameters a and b: 10 20

 

Inside test(double) a: 88 Inside test(double) a: 123.2

 

 

 

As you can see, this version of OverloadDemo does not define test(int). Therefore, when test( ) is called with an integer argument inside Overload, no matching method is found. However, Java can automatically convert an integer into a double, and this conversion can be used to resolve the call. Therefore, after test(int) is not found, Java elevates i to double and then calls test(double). Of course, if test(int) had been defined, it would have been called instead. Java will employ its automatic type conversions only if no exact match is found.

 

Method overloading supports polymorphism because it is one way that Java implements the “one interface, multiple methods” paradigm. To understand how, consider the following. In languages that do not support method overloading, each method must be given a unique name. However, frequently you will want to implement essentially the same method for different types of data. Consider the absolute value function. In languages that do not support overloading, there are usually three or more versions of this function, each with a slightly different name. For instance, in C, the function abs( ) returns the absolute value of an integer, labs( ) returns the absolute value of a long integer, and fabs( ) returns the absolute value of a floating-point value. Since C does not support overloading, each function has its own name, even though all three functions do essentially the same thing. This makes the situation more complex, conceptually, than it actually is. Although the underlying concept of each function is the same, you still have three names to remember. This situation does not occur in Java, because each absolute value method can use the same name. Indeed, Java’s standard class library includes an absolute value method, called abs( ). This method is overloaded by Java’s Math class to handle all numeric types. Java determines which version of abs( ) to call based upon the type of argument.

 

The value of overloading is that it allows related methods to be accessed by use of a common name. Thus, the name abs represents the general action that is being performed. It is left to the compiler to choose the right specific version for a particular circumstance. You, the programmer, need only remember the general operation being performed. Through the application of polymorphism, several names have been reduced to one. Although this example is fairly simple, if you expand the concept, you can see how overloading can help you manage greater complexity.

 

When you overload a method, each version of that method can perform any activity you desire. There is no rule stating that overloaded methods must relate to one another. However, from a stylistic point of view, method overloading implies a relationship. Thus, while you can use the same name to overload unrelated methods, you should not. For example, you could use the name sqr to create methods that return the square of an integer and the square root of a floating-point value. But these two operations are fundamentally different. Applying method overloading in this manner defeats its original purpose. In practice, you should only overload closely related operations.

 

Overloading Constructors

 

In addition to overloading normal methods, you can also overload constructor methods. In fact, for most real-world classes that you create, overloaded constructors will be the norm, not the exception. To understand why, let’s return to the Box class developed in the preceding chapter. Following is the latest version of Box:

 

class Box { double width; double height; double depth;

 

     This is the constructor for Box. Box(double w, double h, double d) {

 

width = w; height = h; depth = d;

 

}

 

     compute and return volume double volume() {

 

return width * height * depth;

 

}

 

}

 

As you can see, the Box( ) constructor requires three parameters. This means that all declarations of Box objects must pass three arguments to the Box( ) constructor. For example, the following statement is currently invalid:

 

Box ob = new Box();

 

Since Box( ) requires three arguments, it’s an error to call it without them. This raises some important questions. What if you simply wanted a box and did not care (or know) what its initial dimensions were? Or, what if you want to be able to initialize a cube by specifying only one value that would be used for all three dimensions? As the Box class is currently written, these other options are not available to you.

 

Fortunately, the solution to these problems is quite easy: simply overload the Box constructor so that it handles the situations just described. Here is a program that contains an improved version of Box that does just that:

 

/*     Here, Box defines three constructors to initialize the dimensions of a box various ways.

 

*/

 

class Box { double width; double height; double depth;

     constructor used when all dimensions specified Box(double w, double h, double d) {

 

width = w; height = h; depth = d;

 

}

 

     constructor used when no dimensions specified Box() {

 

width = -1; // use -1 to indicate height = -1; // an uninitialized

 

depth = -1; // box

 

}

 

     constructor used when cube is created Box(double len) {

 

width = height = depth = len;

 

}

 

     compute and return volume

 

double volume() {

 

return width * height * depth;

 

}

 

}

 

class OverloadCons {

 

public static void main(String args[]) {

 

// create boxes using the various constructors 


Box mybox1 = new Box(10, 20, 15);

 

Box mybox2 = new Box(); Box mycube = new Box(7);

 

double vol;

 

     get volume of first box vol = mybox1.volume();

 

System.out.println("Volume of mybox1 is " + vol);

 

     get volume of second box

 

vol = mybox2.volume(); System.out.println("Volume of mybox2 is " + vol);

// get volume of cube 


vol = mycube.volume();

 

System.out.println("Volume of mycube is " + vol);

 

}

 

}

 

The output produced by this program is shown here:

 

Volume of mybox1 is 3000.0

 

Volume of mybox2 is -1.0

 

Volume of mycube is 343.0

 

As you can see, the proper overloaded constructor is called based upon the parameters specified when new is executed.

 

Study Material, Lecturing Notes, Assignment, Reference, Wiki description explanation, brief detail


Copyright © 2018-2020 BrainKart.com; All Rights Reserved. Developed by Therithal info, Chennai.