3.5. Constructors of a class

[6.3] Create and overload constructors; including impact on default constructors

In this section, you’ll create constructors, learn the differences between default and user-defined constructors, and create overloaded constructors.

What happens when you open a new bank account? Depending on the services your bank provides, you may be assigned a new bank account number, provided with a checkbook, and given access to a new online account the bank has created for you. These details are created and returned to you as part of setting up your new bank account.

Compare these steps with what a constructor does in Java, as illustrated in figure 3.18.

Figure 3.18. The series of steps that may be executed when you create a new bank account. These steps can be compared with what a constructor does in Java.

Constructors are special methods that create and return an object of the class in which they’re defined. Constructors have the same name as the class in which they’re defined, and they don’t specify a return type—not even void.

A constructor can accomplish the following tasks:

  • Call the superclass’s constructor; this can be an implicit or explicit call.
  • Initialize all the instance variables of a class with their default values.

Constructors come in two flavors: user-defined constructors and default constructors, which we’ll cover in detail in the next sections.

3.5.1. User-defined constructors

The author of a class has full control over the definition of the class. An author may or may not define a constructor in a class. If the author defines a constructor in a class, it’s known as a user-defined constructor. Here the word user doesn’t refer to another person or class that uses this class but instead refers to the person who created the class. It’s called “user-defined” because it’s not created by the Java compiler.

Figure 3.19 shows a class Employee that defines a constructor.

Figure 3.19. A class, Employee, with a constructor defined by the user Paul

Here’s a class, Office, that creates an object of class Employee:

In the preceding example, creates an object of class Employee using the keyword new, which triggers the execution of the Employee class constructor. The output of the class Office is as follows:

Constructor

Because a constructor is called as soon as an object is created, you can use it to assign default values to the instance variable of your class, as follows (modified and additional code is highlighted in bold):

Let’s create an object of the class Employee in the class Office and see if there’s any difference:

The output of the preceding code is as follows:

Constructor
20

Because a constructor is a method, you can also pass method parameters to it, as follows (changes are highlighted in bold):

class Employee {
    String name;
    int age;
    Employee(int newAge, String newName) {
        name = newName;
        age = newAge;
        System.out.println("Constructor");
    }
}

You can use this constructor in the class Office by passing to it the required method arguments, as follows:

class Office {
    public static void main(String args[]) {
        Employee emp = new Employee(30, "Pavni Gupta");
    }
}

Revisit the use and declaration of the previously mentioned constructors. Note that a constructor is called when you create an object of a class. A constructor does have an implicit return type, which is the class in which it’s defined. It creates and returns an object of its class, which is why you can’t define a return type for a constructor. Also note that you can define constructors using any of the four access levels.

Exam Tip

You can define a constructor using all four access levels: public, protected, default, and private.

What happens if you define a return type for a constructor? Java will treat it as another method, not a constructor, which also implies that it won’t be called implicitly when you create an object of its class:

In the preceding example, won’t call the method Employee with the return type void defined in the class Employee. Because the method Employee defines its return type as void, it’s no longer treated as a constructor.

If the class Employee defines the return type of the method Employee as void, how can Java use it to create an object? The method (with the return type void) is treated as any other method in the class Employee. This logic applies to all the other data types: if you define the return type of a constructor to be any data type—such as char, int, String, long, double, or any other class—it’ll no longer be treated as a constructor.

How do you execute such a method? By calling it explicitly, as in the following code (modified code is in bold):

Note that the Employee method in the preceding code is called like any other method defined in the class Employee. It doesn’t get called automatically when you create an object of the class Employee. As you can see in the preceding code, it’s allowed to define a method that’s not a constructor in a class with the same name. Interesting.

But note that the authors of the OCA exam also found this interesting, and you’re likely to get a few tricky questions regarding this concept. Don’t worry: with the right information under your belt, you’re sure to answer them correctly.

Exam Tip

A constructor must not define any return type. Instead, it creates and returns an object of the class in which it’s defined. If you define a return type for a constructor, it’ll no longer be treated as a constructor. Instead, it’ll be treated as a regular method, even though it shares the same name as its class.

Initializer blocks versus constructors

An initializer block is defined within a class, not as a part of a method. It executes for every object that’s created for a class. In the following example, the class Employee defines an initializer block:

In the following code, the class TestEmp creates an object of the class Employee:

If you define both an initializer and a constructor for a class, both of these will execute. The initializer block will execute prior to the constructor:

The output of the class TestEmp is as follows:

Employee:initializer
Employee:constructor

If a class defines multiple initializer blocks, their order of execution depends on their placement in a class. But all of them execute before the class’s constructor:

Here’s the output of the preceding code:

Employee:initializer 1
Employee:initializer 2
Employee:constructor

Does the preceding code example leave you wondering why you need both an initializer block and a constructor, if both of these execute upon the creation of an object? Initializer blocks are used to initialize the variables of anonymous classes. An anonymous class is a type of inner class. In the absence of a name, anonymous classes can’t define a constructor and rely on an initializer block to initialize their variables upon the creation of an object of their class. Because inner classes aren’t on this exam, I won’t discuss how to use an initializer block with an anonymous inner class.

A lot of action can happen within an initializer block: It can create local variables. It can access and assign values to instance and static variables. It can call methods and define loops, conditional statements, and try-catch-finally blocks. Unlike constructors, an initializer block can’t accept method parameters.

Note

Loops and conditional statements are covered in chapter 5, and try-catch-finally blocks are covered in chapter 7.

3.5.2. Default constructor

In the previous section on user-defined constructors, I discussed how a constructor is used to create an object. What happens if you don’t define any constructor in a class?

The following code is an example of the class Employee that doesn’t define a constructor:

You can create objects of this class in another class (Office), as follows:

In this case, which method creates the object of the class Employee? Figure 3.20 shows what happens when a class (Employee) is compiled that doesn’t define any constructor. In the absence of a user-defined constructor, Java inserts a default constructor. This constructor doesn’t accept any method arguments. It calls the constructor of the super (parent) class and assigns default values to all the instance variables.

Figure 3.20. When the Java compiler compiles a class that doesn’t define a constructor, the compiler creates one for it.

Exam Tip

The accessibility of a default constructor matches the accessibility of its class. Java creates a public default constructor for a public class. It creates a default constructor with package access for a class with package-level access.

What happens if you add another constructor to the class Employee, as in the following example?

In this case, upon recompilation, the Java compiler will notice that you’ve defined a constructor in the class Employee. It won’t add a default constructor to it, as shown in figure 3.21.

Figure 3.21. When a class with a constructor is compiled, the Java compiler doesn’t add a default constructor to it.

In the absence of a no-argument constructor, the following code will fail to compile:

Exam Tip

Java defines a default constructor if and only if you don’t define a constructor. If a class doesn’t define a constructor, the compiler will add a default, no-argument constructor to the class. But if you modify the class later by adding a constructor to it, the Java compiler will remove the default, no-argument constructor that it initially added to the class.

3.5.3. Overloaded constructors

In the same way in which you can overload methods in a class, you can also overload the constructors in a class. Overloaded constructors follow the same rules as discussed in the previous section for overloaded methods. Here’s a quick recap:

  • Overloaded constructors must be defined using different argument lists.
  • Overloaded constructors can’t be defined by just a change in the access levels.

Because constructors don’t define a return type, there’s no point in defining invalid overloaded constructors with different return types.

The following is an example of an Employee class that defines four overloaded constructors:

In the preceding code, defines a constructor that doesn’t accept any method arguments. defines another constructor that accepts a single method argument. Note the constructors defined at and . Both of these accept two method arguments, String and int. But the placement of these two method arguments is different in and , which is acceptable and valid for overloaded constructors and methods.

Invoking an overloaded constructor from another constructor

It’s common to define multiple constructors in a class and reuse their functionality across constructors. Unlike overloaded methods, which can be invoked using the name of a method, overloaded constructors are invoked by using the keyword this—an implicit reference that’s accessible to all objects that refer to an object itself:

The code at creates a no-argument constructor. At , this constructor calls the overloaded constructor by passing to it values null and 0. defines an overloaded constructor that accepts two method arguments.

Because a constructor is defined using the name of its class, it’s a common mistake to try to invoke a constructor from another constructor using the class’s name:

Also, when you invoke an overloaded constructor using the keyword this, it must be the first statement in your constructor:

You can’t call two (or more) constructors within a constructor because the call to a constructor must be the first statement in a constructor:

That’s not all: you can’t call a constructor from any other method in your class. None of the other methods of the class Employee can invoke its constructor.

Rules to remember

Here’s a quick list of rules to remember for the exam for defining and using overloaded constructors:

  • Overloaded constructors must be defined using different argument lists.
  • Overloaded constructors can’t be defined by just a change in the access levels.
  • Overloaded constructors may be defined using different access levels.
  • A constructor can call another overloaded constructor by using the keyword this.
  • A constructor can’t invoke a constructor by using its class’s name.
  • If present, the call to another constructor must be the first statement in a constructor.
  • You can’t call multiple constructors from a constructor.
  • A constructor can’t be invoked from a method (except by instantiating a class using the new keyword).

The next Twist in the Tale exercise hides an important concept within its code, which you can get to know only if you execute the modified code (answer in the appendix).

Twist in the Tale 3.2

Let’s modify the definition of the class Employee that I used in the section on overloaded constructors, as follows:

class Employee {
    String name;
    int age;
    Employee() {
        this ();
    }
    Employee (String newName, int newAge) {
        name = newName;
        age = newAge;
    }
}

Question: What is the output of this modified code, and why?

Now that you’ve seen how to create methods and constructors, and their overloaded variants, we’ll turn to how all of these can be used to access and modify object fields in the next section.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.143.239.44