answersLogoWhite

0

Overloaded Constructors

Overloading a constructor means typing in multiple versions of the constructor, each having a different argument list, like the following examples:

class Car {

Car() { }

Car(String s) { }

}

The preceding Car class has two overloaded constructors, one that takes a string, and one with no arguments. Because there's no code in the no-arg version, it's actually identical to the default constructor the compiler supplies, but remember-since there's already a constructor in this class (the one that takes a string), the compiler won't supply a default constructor. If you want a no-arg constructor to overload the with-args version you already have, you're going to have to type it yourself, just as in the Car example.

Overloading a constructor is typically used to provide alternate ways for clients to instantiate objects of your class. For example, if a client knows the Car name, they can pass that to a Car constructor that takes a string. But if they don't know the name, the client can call the no-arg constructor and that constructor can supply a default name. Here's what it looks like:

1. public class Car {

2. String name;

3. Car(String name) {

4. this.name = name;

5. }

6.

7. Car() {

8. this(makeRandomName());

9. }

10.

11. static String makeRandomName() {

12. int x = (int) (Math.random() * 5);

13. String name = new String[] {"Ferrari", "Lamborghini",

"Rover", "Spyker",

"Lotus"}[x];

14. return name;

15. }

16.

17. public static void main (String [] args) {

18. Car a = new Car();

19. System.out.println(a.name);

20. Car b = new Car("Proton");

21. System.out.println(b.name);

22. }

23. }

Running the code four times produces this output:

% java Car

Lotus

Proton

% java Car

Ferrari

Proton

% java Car

Rover

Proton

% java Car

Ferrari

Proton

There's a lot going on in the preceding code. Figure 2-7 shows the call stack for constructor invocations when a constructor is overloaded. Take a look at the call stack, and then let's walk through the code straight from the top.

• Line 2 Declare a String instance variable name.

• Lines 3-5 Constructor that takes a String, and assigns it to instance variable name.

• Line 7. Assume every Car needs a name, but the client (calling code) might not always know what the name should be, so you'll assign a random name. The no-arg constructor generates a name by invoking the makeRandomName() method.

• Line 8 The no-arg constructor invokes its own overloaded constructor that takes a String, in effect calling it the same way it would be called if client code were doing a new to instantiate an object, passing it a String for the name. The overloaded invocation uses the keyword this, but uses it as though it were a method name, this(). So line 8 is simply calling the constructor on line 3, passing it a randomly selected String rather than a client-code chosen name.

• Line 11 Notice that the makeRandomName() method is marked static! That's because you cannot invoke an instance (in other words, nonstatic) method (or access an instance variable) until after the super constructor has run. And since the super constructor will be invoked from the constructor on line 3, rather than from the one on line 7, line 8 can use only a static method to generate the name. If we wanted all Cars not specifically named by the caller to have the same default name, say, "Ford," then line 8 could have read this("Ford"); rather than calling a method that returns a string with the randomly chosen name.

• Line 12 This doesn't have anything to do with constructors, but since we're all here to learn...it generates a random integer between 0 and 4.

• Line 13 We're creating a new String object (just a single String instance), but we want the string to be selected randomly from a list. Except we don't have the list, so we need to make it. So in that one line of code we

1. Declare a String variable, name.

2. Create a String array (anonymously-we don't assign the array itself to anything).

3. Retrieve the string at index [x] (x being the random number generated on line 12) of the newly created String array.

4. Assign the string retrieved from the array to the declared instance variable name. We could have made it much easier to read if we'd just written

5. String[] nameList = {"Ferrari", "Lamborghini", "Rover", "Spyker","Lotus"};

6. String name = nameList[x];

• Line 18 We're invoking the no-arg version of the constructor (causing a random name from the list to be passed to the other constructor).

• Line 20 We're invoking the overloaded constructor that takes a string representing the name.

The key point to get from this code example is in line 8. Rather than calling super(), we're calling this(), and this() always means a call to another constructor in the same class. OK, fine, but what happens after the call to this()? Sooner or later the super() constructor gets called, right? Yes indeed. A call to this() just means you're delaying the inevitable. Some constructor, somewhere, must make the call to super().

User Avatar

Wiki User

13y ago

What else can I help you with?