Java

Java Tutorials – Constructor and Overloading Methods

Hello, people..! In this post, we will explore some more aspects of object-oriented programming, which is overloading methods, but before that, I thought it is the right the time to tell you about what a constructor is.

Constructor

The constructor is a special method which is written in a class. This is called exactly once at the time of instantiating an object of that class. Why do we need a constructor anyway? A constructor is meant to have the code for initializing the instance variables or any such process which we wish to do before we start using the object. A constructor looks just like a method, with a few rules. The rules for writing a constructor are –

  1. It is a method with the same name as the class name.
  2. It does not have any return type. Not even void.

Now, keep those two rules in mind, as I show you what a constructor exactly looks like –

class Classroom {
    int capacity;
    
    // This is a constructor!
    //
    // 1. Same name as class name
    // 2. No return type
    public Classroom() {
        capacity = 35;
    }
}

That is a constructor. It is automatically called by the JVM when an object of that class is created. To demonstrate this, have a look at the code below –

class Classroom {
    int capacity;

    public Classroom() {
        System.out.println("Inside Classroom's Constructor...");
        capacity = 35;
    }
}

public class Test {
    public static void main(String[] args) {
        System.out.println("Inside main()...");
        Classroom obj1 = new Classroom();
        System.out.println("Creating another object...");
        Classroom obj2 = new Classroom();
        System.out.println("Done with main()...");
    }
}

The output of the given code is –

Inside main()...
Inside Classroom's Constructor...
Creating another object...
Inside Classroom's Constructor...
Done with main()...

I hope this makes the flow of execution clear. Feel free to comment if you have any doubts!

Constructor with Parameters

So, we’ve seen that a constructor pretty much resembles a method. But like methods, can it take arguments? Yes! We can mention parameters for a constructor just as we do for a method in java. These values must be passed at the time of creating the object. Have a look at the code below –

class Person {
    String name;
    int age;
    
    // A constructor with parameters
    public Person(String personName, int personAge) {
        name = personName;
        age = personAge;
    }
}

class Test {
    public static void main(String[] args) {
        // Providing the arguments while creating object
        Person p = new Person("Chloë Grace Moretz", 19);
    }
}

Overloading Methods in Java

Now let us look at the OOP feature of overloading methods in java. We will come back to the constructor in a minute! Now, imagine you wanted to create a utility class which has a lot of frequently used functions. Let’s say we wanted to create a utility class which has the method for returning the index of the maximum element in an array. So this is how you would normally do it –

class Utility {
    public int max(int[] arr) {
        if (arr == null || arr.length < 1) {
            return -1;
        }
        
        int index = 0;
        int max = arr[0];
        
        for (int i = 1; i < arr.length; ++i) { if (arr[i] > max) {
                max = arr[i];
            }
        }
        
        return index;
    }
}

This is fine, but it can only accept an array of integers, what if you needed to find the index of the maximum element in an array of doubles or long or short or any other data type? Would you create other method named “max2”, “max3”, “max4” and so on..? No, you would have to remember a lot of names. Here’s where overloading helps you! Overloading allows you to create two or more methods of the same name but different signatures. Now, recall from our discussion on Enums and Methods in Java. We defined method signature as, name of the method + the list of parameters. We want the method names to be the same, so we will only alter the list of parameters. Overloading needs no special syntax, it’s just as simple as writing another method with a few restrictions. Let us look at an example –

class Utility {
    public int max(int[] arr) {
        System.out.println("public int max(int[] arr)");
        
        if (arr == null || arr.length < 1) {
            return -1;
        }
        
        int index = 0;
        int max = arr[0];
        
        for (int i = 1; i < arr.length; ++i) { if (arr[i] > max) {
                max = arr[i];
                index = i;
            }
        }
        
        return index;
    }
    
    // Overloaded method max, to
    // accept an array of double
    public int max(double[] arr) {
        System.out.println("public int max(double[] arr)");
        
        if (arr == null || arr.length < 1) {
            return -1;
        }
        
        int index = 0;
        double max = arr[0];
        
        for (int i = 1; i < arr.length; ++i) { if (arr[i] > max) {
                max = arr[i];
                index = i;
            }
        }
        
        return index;
    }
    
    // Overloaded method max, to
    // accept an array of long
    public int max(long[] arr) {
        System.out.println("public int max(long[] arr)");
        
        if (arr == null || arr.length < 1) {
            return -1;
        }
        
        int index = 0;
        long max = arr[0];
        
        for (int i = 1; i < arr.length; ++i) { if (arr[i] > max) {
                max = arr[i];
                index = i;
            }
        }
        
        return index;
    }
}

class Test {
    public static void main(String[] args) {
        Utility obj = new Utility();
        
        int[] intArray = {1, 2, 3, 4, 5, 0, -1, -2};
        double[] doubleArray = {1.2, 2.3, 3.4, 4.5, 5.6, 6.7};
        long[] longArray = {1, 2, 3, 4, 5, 6, 124578};
        
        System.out.println(obj.max(intArray));
        System.out.println(obj.max(doubleArray));
        System.out.println(obj.max(longArray));
    }
}

Can you pause for a moment and guess what the output could be? The output of the code above is –

public int max(int[] arr)
4
public int max(double[] arr)
5
public int max(long[] arr)
6

So what happened here is that, based on the number of arguments passed (here 1) and on the basis of the data type of the arguments passed, Java decides for itself which is the best method to call. When we passed an array of doubles, the method which takes an array of doubles is called. If you can notice, we are not reducing the amount of code written, but it makes our job easy as we have to remember only one name, and based on the data type of the argument passed, the corresponding method is called. This is called Overloading methods. Some rules to keep in mind regarding overloading are –

  • We can overload methods only based on different data type of parameter or different number of parameters. Everything else is irrelevant.
  • So, we cannot overload methods based on return type, or access modifiers (public, private, etc.), or specifiers (static), or exception list.

Well, leave exception lists for now, we’ll look at it later. So based on these rules you could run into overloading problems. Given below are some examples of invalid overloads –

/* ===== ===== ===== ===== */
public void foo(int var) { }
public int foo(int var) { }


/* ===== ===== ===== ===== */
public static int foo(int var) { }
public int foo(int var) { }


/* ===== ===== ===== ===== */
public void foo(int var) { }
private void foo(int var) { }

Overloading is heavily used in the Java library. In fact, we’ve been using it right from our first hello world program! How? The println() method we use has a lot of overloaded methods. If you are working in NetBeans or any other IDE, you can see all these methods. This is how it looks in my NetBeans IDE – Overloading - Overloaded Methods of System.out.println()

Overloading Constructors

So we saw what a constructor was and we saw that it resembles a method in many aspects. So as we can overload methods, can we overload constructors too? Yes! How? It’s just like overloading methods, we just alter the number of parameters or change the data type of the parameters. Have a look at the example below to make things clear –

class Time {
    int hours, minutes, seconds;

    public Time(int hrs) {
        hours = hrs;
    }

    // Overloaded Constructor
    public Time(int hrs, int min) {
        hours = hrs;
        minutes = min;
    }
    
    // Overloaded Constructor
    public Time(int hrs, int min, int sec) {
        hours = hrs;
        minutes = min;
        seconds = sec;
    }
}

class Test {
    public static void main(String[] args) {
        Time t1 = new Time(10);
        Time t2 = new Time(10, 20);
        Time t3 = new Time(10, 20, 30);
        
        System.out.println(t1.hours);
        System.out.println(t1.minutes);
        System.out.println(t1.seconds);
        
        System.out.println(t2.hours);
        System.out.println(t2.minutes);
        System.out.println(t2.seconds);
        
        System.out.println(t3.hours);
        System.out.println(t3.minutes);
        System.out.println(t3.seconds);
    }
}

So that’s how we overload constructors on Java. Using overloaded versions of the constructor, we can initialize selected fields of the object while instantiation. The output of the code above is –

10
0
0
10
20
0
10
20
30

We have also used overloaded constructors before. The Scanner class has many overloaded versions of constructors. We can see it all in NetBeans IDE – Overloading - Overloaded Constructors in Scanner class While there are a lot more things to discuss about the constructor we won’t do it in this post as the requires the knowledge of some other concepts. So, if all I explained above made sense to you, then I will definitely have happy tears! 😛

Order of Preference in Overloading

This is a very advanced concept. Beginners can skip this, but do come back again because this is very interesting! Now we know that an integer value is a match to long data type, as well as for Integer class (for those who know it). So, if all these appear in the form of different overloads, which method would be called? What is the order which Java uses to choose an overloaded method if all the methods are actually a match to the argument provided? Well, let’s say there’s a function named “foo” which is provided with 2 integers, then the order which Java uses is –

Exact Match by Data Type
public void foo(int i, int j) {}
A Larger Primitive Data Type
public void foo(long i, long j) {}
Autoboxed Type
public void foo(Integer i, Integer j) {}
Varargs
public void foo(int... args) {}

To better understand this concept take the code below and run it on your PC –

class OverloadingOrder {
    public void foo(int i, int j) {
        System.out.println("public void foo(int i, int j)");
    }
    
    public void foo(long i, long j) {
        System.out.println("public void foo(long i, long j)");
    }
    
    public void foo(Integer i, Integer j) {
        System.out.println("public void foo(Integer i, Integer j)");
    }
    
    public void foo(int... args) {
        System.out.println("public void foo(int... args)");
    }
}

class Test {
    public static void main(String[] args) {
        OverloadingOrder obj = new OverloadingOrder();
        
        obj.foo(1, 1);
    }
}

Now, try commenting out a few versions of the overloads and observe which function is called. Try it for a few minutes and I’m sure you will understand it! You might think Java follows the order which you write it in the class, but that is irrelevant. Now another thing to note here is that Java will only do at most one implicit conversion while finding the right overloaded match. Take a look at the code below –

class OverloadingOrder {
    public void foo(Double f) {
        System.out.println("public void foo(Double f)");
    }
}

class Test {
    public static void main(String[] args) {
        OverloadingOrder obj = new OverloadingOrder();
        
        obj.foo(1f);    // Compilation error
    }
}

This gives a compilation error saying that Java wasn’t able to find a suitable overloaded method. This is because conversion from float to double value is one implicit conversion but that’s the end of it. Java will not perform another implicit conversion from double to Double. Try such examples in your PC. Try the same thing with int and Long, short and Integer, and so on. I’m sure you’ll get the hang of it after a few tries. 🙂 The last concept I want to discuss in overloading is, overloading in the context of variable number of arguments. An array of integers is a match to both the overloaded methods below –

public void count(int... args) { }
public void count(int[] arr) { }

So, which one is called?? It gives a compilation error! Java cannot differentiate between those two. Of course, the way we normally call those methods is different, but still, Java doesn’t take risks as we could pass an array and wreak havoc! 😛 … So that is a nice little thing to remember. I hope my post gave you a fair understanding of what constructors are and what overloading is. If you have any doubts, feel free to comment them! Keep practicing! Happy Coding!! 😀

3 thoughts on “Java Tutorials – Constructor and Overloading Methods

  1. Hi,

    first of all thanks for such a nice post. But can you please change the content representation. Replace text (with sidewise scroller) with paragraph. It would be really nice and more readable.

Leave a Reply