Constructor
Lesson content
- What is a constructor - idea, declaration
- Default, no-argument, and parameterized constructors
- Most common errors
What is a constructor - idea, declaration
Every time it is necessary to initialize an object, the new command is used. After this reserved word, the class name is always followed by an open and close parentheses. It has already been explained that during initialization, memory space is reserved for the new object. However, after the memory space is reserved, one more thing happens: the constructor is called.
A constructor is a special method that can assign initial values to the object’s attributes during its initialization. This means the class constructor is automatically called every time the new command is used.
The constructor definition is almost the same as a method definition, with two limitations:
- The constructor’s name is always the same as the class name (if named differently, Java will not consider it a constructor, but a regular method).
- Constructors never have a return value (other than the object of that class), so the header does not include even “void.”
Default, no-argument, and parameterized constructors
In previous examples, constructors were not explicitly written for the class. When a class in Java does not have an explicitly written constructor, Java automatically assigns a default constructor to it.
Upon calling, the default constructor sets the attribute values to default values for their data type (int to 0, double to 0.0, boolean to false , String to null, etc.), unless the attribute values are already set to initial values during the declaration.
If a class has an explicitly written constructor, Java does not create a default constructor.
However, in some situations, it is convenient to explicitly write a constructor because initial values can be assigned to attributes during class initialization, or some messages can be printed, etc.
Constructors are divided into two types depending on whether they have parameters or not. The first type is parameterized constructors, and the second is no-argument constructors (which include the default constructor). One default and one explicit constructor are shown in the following example.
Example 1
Create a class FoodItem with two attributes:
- name and
- caloricValue
Assign the initial value “unknown” to the first attribute, and 0.0 to the second.
1 class FoodItem {
2 String name = "unknown";
3 double caloricValue = 0.0;
4 }
Create a class FoodItem2 with two attributes:
- name and
- caloricValue
Create a constructor that assigns the initial value “unknown” to the first attribute, and 0.0 to the second.
1 class FoodItem2 {
2 String name;
3 double caloricValue;
4
5 FoodItem2(){
6 name = "unknown";
7 caloricValue = 0.0;
8 }
9 }
Class FoodItem does not have an explicitly written constructor, so Java assigns a default constructor to it (it is not visible in the code), and initial values are assigned immediately upon attribute declaration.
On the other hand, class FoodItem2 has an explicitly written no-argument constructor (it has no parameters) that assigns initial values to the attributes.
First, it should be noted that, unlike a regular method, the constructor does not have a return value - it does not even use “void”, because it always returns an object of FoodItem class. The constructor header just starts with its name. Second, the constructor’s name is exactly the same as the class name (FoodItem2 - the first letter of each word is capitalized). Finally, it can be seen that the effect of executing the constructor is exactly the same as assigning initial values to attributes immediately upon their declaration.
This means that when initializing an object of class FoodItem, the default constructor, which Java automatically assigned to the class, is called, and the values are assigned to the attributes through their declaration.
1 FoodItem f = new FoodItem();
When initializing an object f2 of class FoodItem2, the explicitly written no-argument constructor is called, which assigns values to the attributes.
1 FoodItem2 f2 = new FoodItem2();
The purpose of the constructor is to initialize an object during creation, bringing it into an initial state. However, in some cases, the constructor needs to do more than just assign initial values to attributes. This is illustrated in the following example.
Example 2
Create a class FoodItem3 with two attributes:
- name and
- caloricValue
Create a constructor that assigns the initial value “unknown” to the first attribute, 0.0 to the second, and prints a message about the initial values of the attributes on the screen.
1 class FoodItem3 {
2 String name;
3 double caloricValue;
4
5 FoodItem3(){
6 name = "unknown";
7 caloricValue = 0.0;
8 System.out.println("Name: " + name);
9 System.out.println("Caloric value: " + caloricValue);
10 }
11 }
The constructor of class FoodItem3 also prints some messages to the screen. In other words, every time an object of this class is initialized, the initial values of its attributes will be printed to the screen:
1 FoodItem3 f3 = new FoodItem3();
2 //It will print to the screen:
3 //Name: unknown
4 //Caloric value: 0.0
Default constructors always set attributes to default values (unless specific values are assigned during declaration). Parameterized constructors, on the other hand, can set attributes to values provided as parameters during object creation. This way, through a single constructor call, one or more attribute values can be assigned, making it much easier to use the class. This can be seen in the following example.
Example 3
Create a class Person with two attributes:
- firstName and
- lastName
Create a constructor that has two parameters, where the first contains a new value for the first name, and the second contains a new value for the last name. This constructor should assign the entered values to the attributes.
1 class Person {
2
3 String firstName;
4 String lastName;
5
6 Person(String firstName1, String lastName1){
7 firstName = firstName1;
8 lastName = lastName1;
9 }
10 }
Create a class TestPerson in which an object of class Person is created and immediately assigned the values “Peter” for the first name and “Smith” for the last name through the constructor.
1 class TestPerson {
2
3 public static void main(String[] args) {
4 // This command will not be accepted because
5 // class Person has one constructor, and it
6 // has two parameters.
7 //Person p1 = new Person();
8
9 //This is how the parameterized constructor of
10 // the Person class is called correctly.
11 Person p1 = new Person("Peter", "Smith");
12 }
13 }
It is common for the parameters of a constructor to have the same name as the attributes (e.g., not firstName1 but firstName), but in this case, the reserved word this must be used inside the constructor to distinguish between the attributes and the parameters. If this is applied to the Person class, the constructor would look like the one in class Person2.
1 class Person2 {
2
3 String firstName;
4 String lastName;
5
6 Person2(String firstName, String lastName){
7 this.firstName = firstName;
8 this.lastName = lastName;
9 }
10 }
A class can have multiple constructors, but they must differ in the number and/or types of parameters. This is called constructor overloading, and it is similar to method overloading.
Example 4
Create a class Car with two attributes:
- licensePlate (e.g., “AA-131”) and
- owner (owner’s full name, e.g., “Mike Stone”)
Create three constructors for this class:
- No-argument constructor
- Parameterized constructor with one parameter for the car owner’s name. This constructor should assign the input value to the owner attribute.
- Parameterized constructor with two parameters, where the first parameter contains the new value for the owner’s name, and the second contains the new value for the license plate. This constructor should assign the input values to the attributes.
Make sure the parameterized constructors have parameters with the same names as the attributes.
1 class Car {
2
3 String licensePlate;
4
5 String owner;
6
7 public Car() {}
8
9 public Car(String owner) {
10 this.owner = owner;
11 }
12
13 /*
14 It is not possible to make this constructor because
15 the parameter list would not differentiate from the
16 previous constructor's parameter list (just one
17 string as a parameter). Overloading the constructor
18 in this way would not be possible.
19
20 public Car(String licensePlate) {
21 this.licensePlate = licensePlate;
22 }*/
23
24 public Car(String owner, String licensePlate) {
25 this.licensePlate = licensePlate;
26 this.owner = owner;
27 }
28 }
Create a class TestCar where three objects of the Car class are created and immediately initialized through constructors with the following values:
- No values are assigned, just the object is initialized
- The owner is “Peter Smith”
- The owner is “Mike Stone”, and the registration is “AA-931”
1 class TestCar {
2
3 public static void main(String[] args) {
4 Car a1 = new Car();
5
6 Car a2 = new Car("Peter Smith");
7
8 Car a3 = new Car("Mike Stone","AA-931");
9 }
10 }
From the TestCar class code, you can see that if a class has multiple constructors, any of them can be called when initializing an object. Furthermore, it is important to note two more things:
- In the Car class, there is a version of the constructor that cannot be written because overloading would not be possible - the list of parameters would be the same as for an existing constructor.
- If the Car class did not explicitly write a no-argument constructor along with the two parameterized constructors, it would not be possible to call it (the call “Car c1 = new Car();” would cause a syntax error). This is because Java would not assign a default constructor to the Car class, as explicit constructors already exist in that class.
Most common errors
Some of the most common syntax errors related to writing constructors are:
- Calling a constructor with the wrong order, number, or type of arguments. For example, if a constructor with the declaration “Room (double numberOfBeds, boolean apartment)” is called like this:
1 Room room = new Room(true, 4);
instead of (correct):
1 Room room = new Room(4, true);
- Calling a no-argument or default constructor if only parameterized constructors are explicitly declared in the class.
Other common errors that are not syntax errors but affect the program’s behavior include:
- Calling a constructor with the wrong order of parameters (which are of the same type, so it is not a syntax error). For example, the constructor “Person (String firstName, String lastName)” is called like this:
1 Person p = new Person("Smith", "Peter");
Here, the attributes firstName and lastName are assigned the wrong values (first name should be “Peter” and last name should be “Smith” - the order is wrong). Instead, the call should be:
1 Person p = new Person("Peter", "Smith");
Writing the constructor name differently from the class name. Java will treat this as a regular method, not a constructor. When attempting to call “such” a constructor, you will get a message that it does not exist.
Writing void or any other return type for a constructor. Although this may not cause a syntax error, Java will treat it as a regular method, not a constructor. When you try to call such a constructor, you will get a message saying it does not exist.
Although it is not a syntax error, novice programmers often forget to use the reserved word this when the constructor parameter has the same name as an attribute. In this case, attempting to assign a value to the attribute will have no effect.