Constructors

An object is an instance of a class used as the template for object creation. Each object is defined by its state and behavior. The object's state is defined by the values of its fields (also called properties), the object behavior by its methods. Since all Java objects are descendants of java.lang.Object, it is not possible to have an object without state and behavior because every object inherits its methods and some basic state from java.lang.Object. But when we talk about application code, classes, and objects this code creates, we mean the methods and state we define in order to build the functionality we want. In this sense, it is possible to have an object without methods. Such objects are usually called data objects, data structures, or data transfer objects. And it is possible to have objects without a state, with methods only. Such objects are often called utilities.

If an object can have a state, the state has to be initialized during object creation. It means that some values have to be assigned to the variables that represent the object fields. This initial assignment can be done either using an assignment operator, =, explicitly or by letting the JVM assign the default values to the object's fields. What these default values are depends on the field type. We have discussed the default value of each type in Chapter 5, Java Language Elements and Types. Primitive numeric types have the default type of zero, the Boolean type false, and the reference type null

An object is created using the operator new. This operator requires specifying the constructor that has to be used for object creation. The primary duty of a constructor is to initialize the object state. But, there are three cases when an explicit definition of a constructor in the class is not required:

How then can an object be created?  The operator new expects the constructor. The answer is that in such a casewhen there is no constructor explicitly defined in a class—a default constructor is generated for the class by the compiler. This default constructor looks like the following:

public ClassName(){
super();
}

As you can see, it does only one thing: calls the constructor (the one without parameters) of the parent class using the keyword super. This parent constructor without parameters may be a default one too, or may be explicitly created. And here resides a possible source of confusion: if a class has an explicitly defined constructor, the default one (without parameters) is not generated automatically. The reason for this limitation is that it puts the programmer in command and lets the class author decide whether to add a constructor without parameters to the class or not. Otherwise, imagine you have created a class, Person, and do not want to allow an instance of this class without certain fields populated. And you do not want these values to be the default ones, but would like to force the client code to populate them explicitly every time a new Person object is created. That's why no constructor is going to be generated automatically behind the scenes as soon as at least one constructorwith or without parametersis defined in a class. Let's test this behavior. Here are two classes without explicitly defined constructors (or any code at all for that matter):

public class Parent {
}
public class
Child extends Parent{
}

We can run the following code just fine:

new Child();

It does not do anything, but that is not the point. Let's add a constructor with a parameter to the parent class:

public class Parent {
public Parent(int i) {
}
}

If we try to create an object of the class Child again, we will get an error:

Click on the red line to see this error message in IntelliJ, because the compiler error message is not as helpful:

It identifies the explicitly defined constructor (with a parameter of type int) as required and its list of parameters as a formal argument list. Meanwhile, a default constructor of the class Child attempts (as we described before) to call a no-arguments constructor of the class Parent and cannot find one. The error wording is not very clear on that.

So, let's add a constructor without parameters to the class Parent:

public class Parent {
public Parent() {
}
public Parent(int i) {
}
}

An object of the class Child can now be created without any problems. That is how the class author can control the process of object creation.

And if you decide that the Parent object has to be created using a constructor with parameters only, you can remove the no-arguments constructor from it again and add to the class Child a constructor that calls the Parent constructor with parameters: 

public class Child extends Parent{
public Child() {
super(10);
}
}

Or, you can add to the child a constructor with parameters:

public class Child extends Parent{
public Child(int i) {
super(i);
}
}

Any of these work just fine.  

From this demonstration, you have probably realized that in order to create an object of a child, all its parent objects have to be created (and their state initialized) first. And it has to be done starting from the most ancient ancestor. Let's look at the following example: 

public class GrandDad{
private String name = "GrandDad";
public GrandDad() {
System.out.println(name);
}
}
public class Parent extends GrandDad{
private String name = "Parent";
public Parent() {
System.out.println(name);
}
}
public class Child extends Parent{
private String name = "Child";
public Child() {
System.out.println(name);
}
}

Can you guess what the output is going to be if we try to create the child new Child()? If you guessed the GrandDad constructor finishes first, then Parent, then Child, you are correct. Here is the result:

The Child constructor calls the Parent constructor, which in turn calls the GrandDad constructor, which calls the java.lang.Object constructor. Only after a parent object has been created (and its constructor has finished doing what it had to do) does the child constructor finish executing, and so on through the chain of parent-child relations. 

After thinking a moment, we decide to derive the value of the field name from the class name. Every Java object has a base class, java.lang.Object, which provides access to the class information via the method getClass(). This method returns an object of the class java.lang.Class with all the information about the class used as a template for the object, including its name. Naturally, we first consider using this.getClass().getName() to get the class name inside Child, Parent, and GrandDad. But, if we start the chain of calls by calling new Child() (as we do in our example), the construct this.getClass().getName() always returns the name of the class Child, even when we use the construct in GrandDad. 

The reason is that, although the keyword this represents the current object (the GrandDad object, for example, if this is used in GrandDad), the method getClass() returns information not about the current object, but about the runtime object (the one that was created by the operator new) which is an instance of Child in this case. That is why, in our example, the construct this.getClass().getName() always returns the name of the class Child, whether this construct is used inside ChildParent, or GrandDad

But there is another way to access the class information that better suits our needs. We can use the class name explicitly, add the extension .class to it, and only then get the class name. Here is an example:

GrandDad.class.getSimpleName(); //always returns "GrandDad"

It seems like it's not much different from using the String literal we used before, does it? Nevertheless, it is an improvement because, if the name of the class changes, the value assigned to the variable NAME will change, too, while in the case of a String literal, its value is not tied to the name of the class automatically.

So, we have added a static field NAME with initialization to each of our three classes:

public class GrandDad{
private static String NAME = GrandDad.class.getSimpleName();
public
GrandDad() {
System.out.println(NAME);
}
}
public class Parent extends GrandDad{
private static String NAME = Parent.class.getSimpleName();
public
Parent() {
System.out.println(NAME);
}
}
public class Child extends Parent{
private static String NAME = Child.class.getSimpleName();
public
Child() {
System.out.println(NAME);
}
}

Notice that we have followed the convention of writing static variable identifiers in uppercase only.  

If we call new Child(), the result will be as follows: 

If we add a constructor with a parameter, the code will look as follows:

public class GrandDad{
private static String NAME = GrandDad.class.getSimpleName()
public
GrandDad() {
System.out.println(NAME);
}
public GrandDad(String familyName) {
System.out.println(familyName + ": " + NAME);
}
}
public class Parent extends GrandDad{
private static String NAME = Parent.class.getSimpleName()
public
Parent() {
System.out.println(NAME);
}
public Parent(String familyName) {
System.out.println(familyName + ": " + NAME);
}
}
public class Child extends Parent{
private static String NAME = Child.class.getSimpleName()
public
Child() {
System.out.println(NAME);
}
public Child(String familyName) {
System.out.println(familyName + ": " + NAME);
}
}

The execution of the line new Child("The Blows") will now change the output only for the child:

That is because the new child's constructor continues to call the parent's constructor without parameters by default. To engage the new parent's constructor, we need to do it explicitly, using the keyword super (we show only the constructors here):

public GrandDad(String familyName) {
System.out.println(familyName + ": " + NAME);
}
public Parent(String familyName) {
super(familyName);
System.out.println(familyName + ": " + NAME);
}
public Child(String familyName) {
super(familyName);
System.out.println(familyName + ": " + NAME);
}

By executing the same line, new Child("The Blows"), we get the desired result:

Please notice that the keyword super has to be the first line of a constructor. If you try to put it anywhere else, an error will be generated. That is because all the constructors have to be completely executed before any other code can be invoked. All the objects in the parent-child chain have to be created and their state initialized first, starting from the topmost base class.

The last constructor-related feature that we would like to mention here is this: one constructor can call another constructor of the same class by using the keyword this. For example, let's say we do not want a family to exist without a family name, but the client code might never be able to supply one. So, we decide to add a default family name to the constructor without parameters:

public class Child extends Parent{
private static String NAME = Child.class.getSimpleName()
public
Child() {
this("The Defaults");
}
public Child(String familyName) {
super(familyName);
System.out.println(familyName + ": " + NAME);
}
}

If we execute the line new Child() again, we will get the following: 

As you can see, the constructors of the same class can be overloaded and call each other the same way the methods do. But constructors are not inherited and thus cannot be hidden or overridden. That is just impossible.

As for any other method, it can be overridden if not private or final. What is private; you probably already have an idea. We will talk about it in more detail in Chapter 7, Packages and Accessibility (Visibility). And we will talk about Final variable in the next section.