Lesson 9.2 Default Constructor
Constructors
This lesson will teach you how to create default constructors for the classes you create. Then, you'll modify the LTextField1 class, adding your new default constructor, so you no longer need to call the init() method when you use your objects. This new version, LTextField2, will make objects that act just like the built-in components.
Constructors are like methods in some ways, and unlike methods in others. Probably the closest comparison is to a static or factory method where you send a message to a class instead of sending a message to an object.
Even that comparison fails in some points, so it's best to mentally put constructors in their own category.
Constructors are defined, like methods, inside a class definition. When you use the new operator to construct an object of your class, the new operator contacts your class, and your class uses the constructor you've written to initialize the object it creates.
Whew! If you think of a class definition as the blueprint for defining objects, then think of the constructor as the factory for creating objects.
Constructor Syntax
Inside your class a constructor looks exactly like a method definition with two constraints:
- A constructor will always have the same name as the class that contains it. There are no exceptions.
- The constructor will have no return type, not even void. Writing a constructor definition using a return type does not create a syntax or runtime error. It just doesn't work. If it has a return type, then it is a method, not a constructor, even if it has the same name as the class.
This illustration [click image to enlarge] shows the basic syntax used for defining a default constructor.

Constructors almost always start with the keyword public, which is always followed by the name of the class. The class name is then followed by a pair of empty parentheses.
Inside the body of the constructor, which is delimited by braces, just like the body of a method, you can have any number of statements. The purpose of the statements is to initialize the fields in your newly created object.
The Default Constructor
The default constructor [sometimes called the no-arg constructor] is the constructor that is called when you supply no arguments. It is called the default constructor because its purpose is to initialize each field in the object to a predefined or default value, so the object is in a usable state.
Here are some default constructors you've already met:
Button btn = new Button();
Label lbl = new Label();
Panel pnl = new Panel(); |
As you can see, sometimes a default constructor is pretty useful, and sometimes it isn't. The Panel object pnl is perfectly functional using the default constructor, but the Button object btn and the Label object lbl are pretty useless as is.
The important thing to see, however, is that, thanks to the default constructor, even Button and Label objects are "well formed"; you won't get a "NullPointerException" message if you try to send lbl the setText() or getText() message. You don't have to do any additional initialization to send messages to each of these objects.
The LTextField2 Class
Let’s create a default constructor for the LTextField class. We'll start by copying LTextField1.java to LTextField2.java and then renaming the class contained in the new file.
|
Why Rename?
|
| Throughout this lesson, I'll make several copies of the LTextFieldX class, renumbering and renaming each one. The only reason for doing this is so that you can see--as well as download and try out--each version of the program as it is developed.
If you want to simply make one LTextField class and modify it as you go, that's fine. |
Next, let's "clean up" the basic structure of the class by changing extends Applet to extends Panel. Even though the Applet class is descended from the Panel class, the Applet class adds a lot of extra functionality that's not really appropriate for our LTextField classes.
Here are the steps you need to follow to create a default constructor for LTextField2:
1. Rename the init()method to LTextField2()
2. Remove the return type of void>
3. In the Label constructor, remove the text "Name", but leave the double quotes. For a default constructor, having a Label with no text makes more sense than a Label that says Name.
4. In the TextField constructor, change the default size to 15 from 40, which is a little long to be useful.
You can see the finished LTextField2.java here:
|
LTextField2.java
|
import java.awt.*;
import java.applet.*;
public class LTextField2 extends Panel
{
Label theLabel;
TextField theText;
public LTextField2()
{
theLabel = new Label("Name:",
Label.RIGHT);
theText = new TextField(15);
add(theLabel);
add(theText);
}
} |
Let's also make a new program to test LTextField2 by copying User1.java to User2.java. Here are the changes you'll have to make to User2.java:
1. As with LTextField1, you'll have to change the name of the class from User1 to User2.
2. Change the type of each field to LTextField2, and change the constructor invocation from new LTextField1() to new LTextField2().
3. Remove the init() messages sent to each of the fields inside the User2 init() method.
|
User2.java
|
import java.awt.*;
import java.applet.*;
public class User2 extends Applet
{
LTextField2 first = new LTextField2();
LTextField2 second = new LTextField2();
public void init()
{
first.init();
second.init();
add(first);
add(second);
}
} |
When you're finished, create User2.html, compile your program and run. As you can see, the program works a little different than it did before. For one thing, the Label is invisible and the TextFields are smaller.
The biggest change, however, is not visible on the surface; this time, you didn't have to send an init() message to each of your objects. Instead, they worked just like the built-in objects.
|
But new LTextField1() Worked. Why?
|
| In User1.java, before you even started thinking about constructors, you created an LTextField1 object like this:
LTextField1 first = new LTextField1();
Since the LTextField1 class didn't have a default constructor, then why did this work at all?
The truth is, you don't have to write a constructor. If your class does not contain a constructor, then Java will "write" a default constructor for you, as it did for LTextField1.
This automatically written constructor doesn't actually do any initialization, and, if you write any constructors at all, Java will no longer write the default constructor. |
Constructive Evaluation
The purpose for writing a default constructor is to put your objects into a "known" state when they are created. But a known state is not the same as an ideal state. For instance, a Label or Button with no text are not very useful.
The same thing is true with the LTextField2 constructor. It has made our objects easier to use: we don't have to send the init() message to each object to complete the initialization, but we still aren't where we'd like to be. We still can't easily create a labeled text field that says "Address:", for instance.
For that, you'll have to wait till the next lesson when you learn to write a variety of overloaded constructors.
Something to Talk About
At the end of the previous section, you were asked to describe two components that you could create using existing components. What default initialization needs to occur in the default constructor for each of your components?
Please continue to the next section of this lesson.
|