November 28, 2014
Hot Topics:

Inside Constructors

  • July 15, 2005
  • By Matt Weisfeld
  • Send Email »
  • More Articles »
This series is intended for anyone who needs to understand fundamental object-oriented concepts before jumping into the code. It can also be used by those who are already coding in an OOP language but do not fully understand the nuances behind the code. Fully understanding the infrustructure of the concepts may improve your coding. These concepts are part of the foundation that any programmer will need to make the paradigm shift from procedural programming to object-oriented programming. See the article The Object-Oriented Thought Process to start at the beginning of the series.

In keeping with the code examples used in the previous articles, Java will be the language used to implement the concepts in code. One of the reasons that I like to use Java is because you can download the Java compiler for personal use at the Sun Microsystems Web site, http://java.sun.com/. You can download the J2SE 1.4.2 SDK (software development kit) to compile and execute these applications and I will provide the code listings for all examples in this article. I have the SDK 1.4.0 loaded on my machine. I will also provide figures and the output (when appropriate) for these examples. See the previous articles in this series for detailed descriptions for compiling and running all the code examples in this series.

In the last column Object Construction, I began a discussion about constructors. Designing effective constructors is one of the responsibilities that must be taken care of when creating classes. In the previous column, I covered constructor basics as well as some finer points of constructor design. Remember that proper construction puts the object in a safe-state. In this article, you will delve deeper into code as you uncover many of the implementation issues of designing constructors.

The Default Constructor

In the previous column, you spent much effort in describing some of the design issues regarding constructors. In this column, you'll investigate and analyze some of the bytecodes that are generated by the Java compiler when it encounters constructors.

First, you will define a simple application that you will use as the basis for this exercise. The initial pass at this application will contain the following classes included in Listing 1:

Listing 1

// Class Shape
public class Shape {

}
//Class TestShape
public class TestShape {
   public static void main (String args[]){
   Shape s = new Shape();
   }
}

This application contains two very small classes. The Shape class actually contains no implementation—or so it may seem. The TestShape class is the actual application (because it contains main()). In this case, the application creates one instance of a Shape class. When this application is run, you get the output presented in Figure 1—which, as expected, is nothing.



Click here for a larger image.

Figure 1

Even though the application is not producing any output, and despite the fact that there is no code in the Shape class, there is action going on behind the scenes.

As you learned in the previous column, if the class provides no explicit constructor, such as in C++, Java, and so forth, the compiler will provide a default constructor. The structure of the default constructor would look like the code in Listing 2:

Listing 2

// Class Shape
public class Shape {
public Shape() { // not actually in source code }
}

It is important to realize that this code is only inserted in the bytecodes generated by the compiler. The default constructor does not show up at all in the source code. In fact, if you decompiled the bytecodes, you would see it then.

After the memory is allocated, the default constructor calls the constructor of the superclass—if there is one (actually there is always a super class—every written Java class ultimately will implicitly inherit from the Object class).

Now, look at these points much more closely.

The Java distribution comes with a binary application called  javap. This application will actually take bytecodes and re-engineer them into something resembling the original source code. There are several Java decompilers currently available; however, because javap is provided with the Java distribution and it serves the purpose here, you will use this tool.

You can call  javap from the console by using the following command-line call:

C:j2sdk1.4.2_05binjavap -classpath . Shape

In this case, you are using  javap to decompile the Shape class. As you can see in Figure 2, the output includes the default constructor in the Shape class even though it was not in the original source code. To review, the default constructor has no parameters.



Click here for a larger image.

Figure 2

It is also interesting to note that the Shape class actually extends  java.lang.Object, just as you would expect. (Remember that all classes in Java ultimately inherit from the Object class.)

This is proof that the compiler actually inserts the default constructor into the Shape class—and in any class that does not provide a constructor.

The key phrase here is in any class that does not provide a constructor. Now, add a non-default constructor to the code as illustrated in Listing 3.

Listing 3

// Class Shape
public class Shape {
   public Shape(int x) {
   }
}
//Class TestShape
public class TestShape {
   public static void main (String args[]){
   Shape s = new Shape(5);    // must pass an integer
   }
}

In Listing 3, you have added a constructor that takes one integer parameter. Thus, you must pass an integer to the constructor when you instantiate a Shape object.

Now, if you run the Shape class through  javap, you get the results in Figure 3.



Click here for a larger image.

Figure 3

Note now that the default constructor does not show up in the decompiled code of the Shape class. Again, this is more proof of the implementation issue that you may have studied in an object-oriented book or class—that the default constructor is provided only if you do not provide your own constructor. As long as you provide at least one constructor in the code, the compiler will not add the default.

What happens if you provide a default constructor? You can actually do this—because the definition of the default constructor is simply a constructor with no parameters. Take a look at Listing 4.

Listing 4

// Class Shape
public class Shape {
   public Shape() {
   }
}

In this case, you are simply doing what the compiler would do; however, there is one major difference. In this case you can add code specific to the construction of the object. Look at the output when you run the Shape class (from Listing 4) through  javap.



Click here for a larger image.

Figure 4

The output in Figure 4 is identical to the output in Listing 3. This is further evidence that the default constructor provided by the compiler is identical to the default constructor that you can provide in your code.





Page 1 of 2



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Sitemap | Contact Us

Rocket Fuel